﻿#include "Envir.h"
#include "../../Shared/Globals.h"
#include "../../Shared/ServerPackets.h"
#include "../../Shared/Language.h"
#include "Robot.h"
#include "../MirDatabase/MailInfo.h"
#include "../../Shared/Data/Stat.h"

using namespace Server::Library::Utils;
using namespace Server::MirDatabase;
using namespace Server::MirNetwork;
using namespace Server::MirObjects;
namespace S = ServerPackets;

namespace Server::MirEnvir
{

int RandomProvider::seed = Environment::TickCount;
ThreadLocal<Random*> *const RandomProvider::RandomWrapper = new ThreadLocal<Random*>([&] ()
{
            return new Random(Interlocked::Increment(seed));
});

    Random *RandomProvider::GetThreadRandom()
    {
        return RandomWrapper->Value;
    }

    int RandomProvider::Next()
    {
        return RandomWrapper->Value->Next();
    }

    int RandomProvider::Next(int maxValue)
    {
        return RandomWrapper->Value->Next(maxValue);
    }

    int RandomProvider::Next(int minValue, int maxValue)
    {
        return RandomWrapper->Value->Next(minValue, maxValue);
    }

Envir *Envir::Main = new Envir();
Envir *Envir::Edit = new Envir();

    Envir *Envir::getMain()
    {
        return Main;
    }

    Envir *Envir::getEdit()
    {
        return Edit;
    }

    Server::MessageQueue *Envir::getMessageQueue()
    {
        return MessageQueue::getInstance();
    }

const std::string Envir::DatabasePath = FileSystem::combine(".", "Server.MirDB");
const std::string Envir::AccountPath = FileSystem::combine(".", "Server.MirADB");
const std::string Envir::BackUpPath = FileSystem::combine(".", "Back Up");
Regex *Envir::AccountIDReg;
Regex *Envir::PasswordReg;
Regex *Envir::EMailReg;
Regex *Envir::CharacterReg;
int Envir::LoadVersion = 0;
int Envir::LoadCustomVersion = 0;

    long long Envir::getTime() const
    {
        return Time;
    }

    void Envir::setTime(long long value)
    {
        Time = value;
    }

std::vector<std::string> Envir::DisabledCharNames;
std::vector<std::string> Envir::LineMessages;

    DateTime Envir::getNow() const
    {
        return _startTime.AddMilliseconds(getTime());
    }

    bool Envir::getRunning() const
    {
        return Running;
    }

    void Envir::setRunning(bool value)
    {
        Running = value;
    }

unsigned int Envir::_objectID = 0;

    unsigned int Envir::getObjectID() const
    {
        return ++_objectID;
    }

int Envir::_playerCount = 0;

    int Envir::getPlayerCount() const
    {
        return Players.size();
    }

HttpServer *Envir::http;

    Envir::StaticConstructor::StaticConstructor()
    {
        AccountIDReg = new Regex(R"(^[A-Za-z0-9]{)" + std::to_string(Globals::MinAccountIDLength) + "," + std::to_string(Globals::MaxAccountIDLength) + "}$");
        PasswordReg = new Regex(R"(^[A-Za-z0-9]{)" + std::to_string(Globals::MinPasswordLength) + "," + std::to_string(Globals::MaxPasswordLength) + "}$");
        EMailReg = new Regex(R"(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)");
        CharacterReg = new Regex(R"(^[\u4e00-\u9fa5_A-Za-z0-9]{)" + std::to_string(Globals::MinCharacterNameLength) + "," + std::to_string(Globals::MaxCharacterNameLength) + "}$");
    }

Envir::StaticConstructor Envir::staticConstructor;
int Envir::LastCount = 0;
int Envir::LastRealCount = 0;
long long Envir::LastRunTime = 0;

    bool Envir::MagicExists(Spell spell)
    {
        for (auto i = 0; i < MagicInfoList.size(); i++)
        {
            if (MagicInfoList[i]->Spell == spell)
            {
                return true;
            }
        }
        return false;
    }

    void Envir::UpdateMagicInfo()
    {
        for (auto i = 0; i < MagicInfoList.size(); i++)
        {
            switch (MagicInfoList[i]->Spell)
            {
                    //warrior
                case Spell::Thrusting:
                    MagicInfoList[i]->MultiplierBase = 0.25f;
                    MagicInfoList[i]->MultiplierBonus = 0.25f;
                    break;
                case Spell::HalfMoon:
                    MagicInfoList[i]->MultiplierBase = 0.3f;
                    MagicInfoList[i]->MultiplierBonus = 0.1f;
                    break;
                case Spell::ShoulderDash:
                    MagicInfoList[i]->MPowerBase = 4;
                    break;
                case Spell::TwinDrakeBlade:
                    MagicInfoList[i]->MultiplierBase = 0.8f;
                    MagicInfoList[i]->MultiplierBonus = 0.1f;
                    break;
                case Spell::FlamingSword:
                    MagicInfoList[i]->MultiplierBase = 1.4f;
                    MagicInfoList[i]->MultiplierBonus = 0.4f;
                    break;
                case Spell::CrossHalfMoon:
                    MagicInfoList[i]->MultiplierBase = 0.4f;
                    MagicInfoList[i]->MultiplierBonus = 0.1f;
                    break;
                case Spell::BladeAvalanche:
                    MagicInfoList[i]->MultiplierBase = 1.0f;
                    MagicInfoList[i]->MultiplierBonus = 0.4f;
                    break;
                case Spell::SlashingBurst:
                    MagicInfoList[i]->MultiplierBase = 3.25f;
                    MagicInfoList[i]->MultiplierBonus = 0.25f;
                    break;
                    //wiz
                case Spell::Repulsion:
                    MagicInfoList[i]->MPowerBase = 4;
                    break;
                    //tao
                case Spell::Poisoning:
                    MagicInfoList[i]->MPowerBase = 0;
                    break;
                case Spell::Curse:
                    MagicInfoList[i]->MPowerBase = 20;
                    break;
                case Spell::Plague:
                    MagicInfoList[i]->MPowerBase = 0;
                    MagicInfoList[i]->PowerBase = 0;
                    break;
                    //sin
                case Spell::FatalSword:
                    MagicInfoList[i]->MPowerBase = 20;
                    break;
                case Spell::DoubleSlash:
                    MagicInfoList[i]->MultiplierBase = 0.8f;
                    MagicInfoList[i]->MultiplierBonus = 0.1f;
                    break;
                case Spell::FireBurst:
                    MagicInfoList[i]->MPowerBase = 4;
                    break;
                case Spell::MoonLight:
                    MagicInfoList[i]->MPowerBase = 20;
                    break;
                case Spell::DarkBody:
                    MagicInfoList[i]->MPowerBase = 20;
                    break;
                case Spell::Hemorrhage:
                    MagicInfoList[i]->MultiplierBase = 0.2f;
                    MagicInfoList[i]->MultiplierBonus = 0.05f;
                    break;
                case Spell::CrescentSlash:
                    MagicInfoList[i]->MultiplierBase = 1.0f;
                    MagicInfoList[i]->MultiplierBonus = 0.4f;
                    break;
            }
        }
    }

    void Envir::FillMagicInfoList()
    {
        //Warrior
        if (!MagicExists(Spell::Fencing))
        {
            MagicInfo *tempVar = new MagicInfo();
            tempVar->Name = "Fencing";
            tempVar->Spell = Spell::Fencing;
            tempVar->Icon = 2;
            tempVar->Level1 = 7;
            tempVar->Level2 = 9;
            tempVar->Level3 = 12;
            tempVar->Need1 = 270;
            tempVar->Need2 = 600;
            tempVar->Need3 = 1300;
            tempVar->Range = 0;
            MagicInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Slaying))
        {
            MagicInfo *tempVar2 = new MagicInfo();
            tempVar2->Name = "Slaying";
            tempVar2->Spell = Spell::Slaying;
            tempVar2->Icon = 6;
            tempVar2->Level1 = 15;
            tempVar2->Level2 = 17;
            tempVar2->Level3 = 20;
            tempVar2->Need1 = 500;
            tempVar2->Need2 = 1100;
            tempVar2->Need3 = 1800;
            tempVar2->Range = 0;
            MagicInfoList.push_back(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Thrusting))
        {
            MagicInfo *tempVar3 = new MagicInfo();
            tempVar3->Name = "Thrusting";
            tempVar3->Spell = Spell::Thrusting;
            tempVar3->Icon = 11;
            tempVar3->Level1 = 22;
            tempVar3->Level2 = 24;
            tempVar3->Level3 = 27;
            tempVar3->Need1 = 2000;
            tempVar3->Need2 = 3500;
            tempVar3->Need3 = 6000;
            tempVar3->Range = 0;
            tempVar3->MultiplierBase = 0.25f;
            tempVar3->MultiplierBonus = 0.25f;
            MagicInfoList.push_back(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::HalfMoon))
        {
            MagicInfo *tempVar4 = new MagicInfo();
            tempVar4->Name = "HalfMoon";
            tempVar4->Spell = Spell::HalfMoon;
            tempVar4->Icon = 24;
            tempVar4->Level1 = 26;
            tempVar4->Level2 = 28;
            tempVar4->Level3 = 31;
            tempVar4->Need1 = 5000;
            tempVar4->Need2 = 8000;
            tempVar4->Need3 = 14000;
            tempVar4->BaseCost = 3;
            tempVar4->Range = 0;
            tempVar4->MultiplierBase = 0.3f;
            tempVar4->MultiplierBonus = 0.1f;
            MagicInfoList.push_back(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ShoulderDash))
        {
            MagicInfo *tempVar5 = new MagicInfo();
            tempVar5->Name = "ShoulderDash";
            tempVar5->Spell = Spell::ShoulderDash;
            tempVar5->Icon = 26;
            tempVar5->Level1 = 30;
            tempVar5->Level2 = 32;
            tempVar5->Level3 = 34;
            tempVar5->Need1 = 3000;
            tempVar5->Need2 = 4000;
            tempVar5->Need3 = 6000;
            tempVar5->BaseCost = 4;
            tempVar5->LevelCost = 4;
            tempVar5->DelayBase = 2500;
            tempVar5->Range = 0;
            tempVar5->MPowerBase = 4;
            MagicInfoList.push_back(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::TwinDrakeBlade))
        {
            MagicInfo *tempVar6 = new MagicInfo();
            tempVar6->Name = "TwinDrakeBlade";
            tempVar6->Spell = Spell::TwinDrakeBlade;
            tempVar6->Icon = 37;
            tempVar6->Level1 = 32;
            tempVar6->Level2 = 34;
            tempVar6->Level3 = 37;
            tempVar6->Need1 = 4000;
            tempVar6->Need2 = 6000;
            tempVar6->Need3 = 10000;
            tempVar6->BaseCost = 10;
            tempVar6->Range = 0;
            tempVar6->MultiplierBase = 0.8f;
            tempVar6->MultiplierBonus = 0.1f;
            MagicInfoList.push_back(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Entrapment))
        {
            MagicInfo *tempVar7 = new MagicInfo();
            tempVar7->Name = "Entrapment";
            tempVar7->Spell = Spell::Entrapment;
            tempVar7->Icon = 46;
            tempVar7->Level1 = 32;
            tempVar7->Level2 = 35;
            tempVar7->Level3 = 37;
            tempVar7->Need1 = 2000;
            tempVar7->Need2 = 3500;
            tempVar7->Need3 = 5500;
            tempVar7->BaseCost = 15;
            tempVar7->LevelCost = 3;
            tempVar7->Range = 9;
            MagicInfoList.push_back(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FlamingSword))
        {
            MagicInfo *tempVar8 = new MagicInfo();
            tempVar8->Name = "FlamingSword";
            tempVar8->Spell = Spell::FlamingSword;
            tempVar8->Icon = 25;
            tempVar8->Level1 = 35;
            tempVar8->Level2 = 37;
            tempVar8->Level3 = 40;
            tempVar8->Need1 = 2000;
            tempVar8->Need2 = 4000;
            tempVar8->Need3 = 6000;
            tempVar8->BaseCost = 7;
            tempVar8->Range = 0;
            tempVar8->MultiplierBase = 1.4f;
            tempVar8->MultiplierBonus = 0.4f;
            MagicInfoList.push_back(tempVar8);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::LionRoar))
        {
            MagicInfo *tempVar9 = new MagicInfo();
            tempVar9->Name = "LionRoar";
            tempVar9->Spell = Spell::LionRoar;
            tempVar9->Icon = 42;
            tempVar9->Level1 = 36;
            tempVar9->Level2 = 39;
            tempVar9->Level3 = 41;
            tempVar9->Need1 = 5000;
            tempVar9->Need2 = 8000;
            tempVar9->Need3 = 12000;
            tempVar9->BaseCost = 14;
            tempVar9->LevelCost = 4;
            tempVar9->Range = 0;
            MagicInfoList.push_back(tempVar9);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::CrossHalfMoon))
        {
            MagicInfo *tempVar10 = new MagicInfo();
            tempVar10->Name = "CrossHalfMoon";
            tempVar10->Spell = Spell::CrossHalfMoon;
            tempVar10->Icon = 33;
            tempVar10->Level1 = 38;
            tempVar10->Level2 = 40;
            tempVar10->Level3 = 42;
            tempVar10->Need1 = 7000;
            tempVar10->Need2 = 11000;
            tempVar10->Need3 = 16000;
            tempVar10->BaseCost = 6;
            tempVar10->Range = 0;
            tempVar10->MultiplierBase = 0.4f;
            tempVar10->MultiplierBonus = 0.1f;
            MagicInfoList.push_back(tempVar10);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar10' statement was not added since tempVar10 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::BladeAvalanche))
        {
            MagicInfo *tempVar11 = new MagicInfo();
            tempVar11->Name = "BladeAvalanche";
            tempVar11->Spell = Spell::BladeAvalanche;
            tempVar11->Icon = 43;
            tempVar11->Level1 = 38;
            tempVar11->Level2 = 41;
            tempVar11->Level3 = 43;
            tempVar11->Need1 = 5000;
            tempVar11->Need2 = 8000;
            tempVar11->Need3 = 12000;
            tempVar11->BaseCost = 14;
            tempVar11->LevelCost = 4;
            tempVar11->Range = 0;
            tempVar11->MultiplierBonus = 0.3f;
            MagicInfoList.push_back(tempVar11);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar11' statement was not added since tempVar11 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ProtectionField))
        {
            MagicInfo *tempVar12 = new MagicInfo();
            tempVar12->Name = "ProtectionField";
            tempVar12->Spell = Spell::ProtectionField;
            tempVar12->Icon = 50;
            tempVar12->Level1 = 39;
            tempVar12->Level2 = 42;
            tempVar12->Level3 = 45;
            tempVar12->Need1 = 6000;
            tempVar12->Need2 = 12000;
            tempVar12->Need3 = 18000;
            tempVar12->BaseCost = 23;
            tempVar12->LevelCost = 6;
            tempVar12->Range = 0;
            MagicInfoList.push_back(tempVar12);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar12' statement was not added since tempVar12 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Rage))
        {
            MagicInfo *tempVar13 = new MagicInfo();
            tempVar13->Name = "Rage";
            tempVar13->Spell = Spell::Rage;
            tempVar13->Icon = 49;
            tempVar13->Level1 = 44;
            tempVar13->Level2 = 47;
            tempVar13->Level3 = 50;
            tempVar13->Need1 = 8000;
            tempVar13->Need2 = 14000;
            tempVar13->Need3 = 20000;
            tempVar13->BaseCost = 20;
            tempVar13->LevelCost = 5;
            tempVar13->Range = 0;
            MagicInfoList.push_back(tempVar13);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar13' statement was not added since tempVar13 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::CounterAttack))
        {
            MagicInfo *tempVar14 = new MagicInfo();
            tempVar14->Name = "CounterAttack";
            tempVar14->Spell = Spell::CounterAttack;
            tempVar14->Icon = 72;
            tempVar14->Level1 = 47;
            tempVar14->Level2 = 51;
            tempVar14->Level3 = 55;
            tempVar14->Need1 = 7000;
            tempVar14->Need2 = 11000;
            tempVar14->Need3 = 15000;
            tempVar14->BaseCost = 12;
            tempVar14->LevelCost = 4;
            tempVar14->DelayBase = 24000;
            tempVar14->Range = 0;
            tempVar14->MultiplierBonus = 0.4f;
            MagicInfoList.push_back(tempVar14);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar14' statement was not added since tempVar14 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SlashingBurst))
        {
            MagicInfo *tempVar15 = new MagicInfo();
            tempVar15->Name = "SlashingBurst";
            tempVar15->Spell = Spell::SlashingBurst;
            tempVar15->Icon = 55;
            tempVar15->Level1 = 50;
            tempVar15->Level2 = 53;
            tempVar15->Level3 = 56;
            tempVar15->Need1 = 10000;
            tempVar15->Need2 = 16000;
            tempVar15->Need3 = 24000;
            tempVar15->BaseCost = 25;
            tempVar15->LevelCost = 4;
            tempVar15->MPowerBase = 1;
            tempVar15->PowerBase = 3;
            tempVar15->DelayBase = 14000;
            tempVar15->DelayReduction = 4000;
            tempVar15->Range = 0;
            tempVar15->MultiplierBase = 3.25f;
            tempVar15->MultiplierBonus = 0.25f;
            MagicInfoList.push_back(tempVar15);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar15' statement was not added since tempVar15 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Fury))
        {
            MagicInfo *tempVar16 = new MagicInfo();
            tempVar16->Name = "Fury";
            tempVar16->Spell = Spell::Fury;
            tempVar16->Icon = 76;
            tempVar16->Level1 = 45;
            tempVar16->Level2 = 48;
            tempVar16->Level3 = 51;
            tempVar16->Need1 = 8000;
            tempVar16->Need2 = 14000;
            tempVar16->Need3 = 20000;
            tempVar16->BaseCost = 10;
            tempVar16->LevelCost = 4;
            tempVar16->DelayBase = 600000;
            tempVar16->DelayReduction = 120000;
            tempVar16->Range = 0;
            MagicInfoList.push_back(tempVar16);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar16' statement was not added since tempVar16 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ImmortalSkin))
        {
            MagicInfo *tempVar17 = new MagicInfo();
            tempVar17->Name = "ImmortalSkin";
            tempVar17->Spell = Spell::ImmortalSkin;
            tempVar17->Icon = 80;
            tempVar17->Level1 = 60;
            tempVar17->Level2 = 61;
            tempVar17->Level3 = 62;
            tempVar17->Need1 = 1560;
            tempVar17->Need2 = 2200;
            tempVar17->Need3 = 3000;
            tempVar17->BaseCost = 10;
            tempVar17->LevelCost = 4;
            tempVar17->DelayBase = 600000;
            tempVar17->DelayReduction = 120000;
            tempVar17->Range = 0;
            MagicInfoList.push_back(tempVar17);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar17' statement was not added since tempVar17 was passed to a method or constructor. Handle memory management manually.
        }

        //Wizard
        if (!MagicExists(Spell::FireBall))
        {
            MagicInfo *tempVar18 = new MagicInfo();
            tempVar18->Name = "FireBall";
            tempVar18->Spell = Spell::FireBall;
            tempVar18->Icon = 0;
            tempVar18->Level1 = 7;
            tempVar18->Level2 = 9;
            tempVar18->Level3 = 11;
            tempVar18->Need1 = 200;
            tempVar18->Need2 = 350;
            tempVar18->Need3 = 700;
            tempVar18->BaseCost = 3;
            tempVar18->LevelCost = 2;
            tempVar18->MPowerBase = 8;
            tempVar18->PowerBase = 2;
            tempVar18->Range = 9;
            MagicInfoList.push_back(tempVar18);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar18' statement was not added since tempVar18 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Repulsion))
        {
            MagicInfo *tempVar19 = new MagicInfo();
            tempVar19->Name = "Repulsion";
            tempVar19->Spell = Spell::Repulsion;
            tempVar19->Icon = 7;
            tempVar19->Level1 = 12;
            tempVar19->Level2 = 15;
            tempVar19->Level3 = 19;
            tempVar19->Need1 = 500;
            tempVar19->Need2 = 1300;
            tempVar19->Need3 = 2200;
            tempVar19->BaseCost = 2;
            tempVar19->LevelCost = 2;
            tempVar19->Range = 0;
            tempVar19->MPowerBase = 4;
            MagicInfoList.push_back(tempVar19);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar19' statement was not added since tempVar19 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ElectricShock))
        {
            MagicInfo *tempVar20 = new MagicInfo();
            tempVar20->Name = "ElectricShock";
            tempVar20->Spell = Spell::ElectricShock;
            tempVar20->Icon = 19;
            tempVar20->Level1 = 13;
            tempVar20->Level2 = 18;
            tempVar20->Level3 = 24;
            tempVar20->Need1 = 530;
            tempVar20->Need2 = 1100;
            tempVar20->Need3 = 2200;
            tempVar20->BaseCost = 3;
            tempVar20->LevelCost = 1;
            tempVar20->Range = 9;
            MagicInfoList.push_back(tempVar20);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar20' statement was not added since tempVar20 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::GreatFireBall))
        {
            MagicInfo *tempVar21 = new MagicInfo();
            tempVar21->Name = "GreatFireBall";
            tempVar21->Spell = Spell::GreatFireBall;
            tempVar21->Icon = 4;
            tempVar21->Level1 = 15;
            tempVar21->Level2 = 18;
            tempVar21->Level3 = 21;
            tempVar21->Need1 = 2000;
            tempVar21->Need2 = 2700;
            tempVar21->Need3 = 3500;
            tempVar21->BaseCost = 5;
            tempVar21->LevelCost = 1;
            tempVar21->MPowerBase = 6;
            tempVar21->PowerBase = 10;
            tempVar21->Range = 9;
            MagicInfoList.push_back(tempVar21);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar21' statement was not added since tempVar21 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::HellFire))
        {
            MagicInfo *tempVar22 = new MagicInfo();
            tempVar22->Name = "HellFire";
            tempVar22->Spell = Spell::HellFire;
            tempVar22->Icon = 8;
            tempVar22->Level1 = 16;
            tempVar22->Level2 = 20;
            tempVar22->Level3 = 24;
            tempVar22->Need1 = 700;
            tempVar22->Need2 = 2700;
            tempVar22->Need3 = 3500;
            tempVar22->BaseCost = 10;
            tempVar22->LevelCost = 3;
            tempVar22->MPowerBase = 14;
            tempVar22->PowerBase = 6;
            tempVar22->Range = 0;
            MagicInfoList.push_back(tempVar22);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar22' statement was not added since tempVar22 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ThunderBolt))
        {
            MagicInfo *tempVar23 = new MagicInfo();
            tempVar23->Name = "ThunderBolt";
            tempVar23->Spell = Spell::ThunderBolt;
            tempVar23->Icon = 10;
            tempVar23->Level1 = 17;
            tempVar23->Level2 = 20;
            tempVar23->Level3 = 23;
            tempVar23->Need1 = 500;
            tempVar23->Need2 = 2000;
            tempVar23->Need3 = 3500;
            tempVar23->BaseCost = 9;
            tempVar23->LevelCost = 2;
            tempVar23->MPowerBase = 8;
            tempVar23->MPowerBonus = 20;
            tempVar23->PowerBase = 9;
            tempVar23->Range = 9;
            MagicInfoList.push_back(tempVar23);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar23' statement was not added since tempVar23 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Teleport))
        {
            MagicInfo *tempVar24 = new MagicInfo();
            tempVar24->Name = "Teleport";
            tempVar24->Spell = Spell::Teleport;
            tempVar24->Icon = 20;
            tempVar24->Level1 = 19;
            tempVar24->Level2 = 22;
            tempVar24->Level3 = 25;
            tempVar24->Need1 = 350;
            tempVar24->Need2 = 1000;
            tempVar24->Need3 = 2000;
            tempVar24->BaseCost = 10;
            tempVar24->LevelCost = 3;
            tempVar24->Range = 0;
            MagicInfoList.push_back(tempVar24);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar24' statement was not added since tempVar24 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FireBang))
        {
            MagicInfo *tempVar25 = new MagicInfo();
            tempVar25->Name = "FireBang";
            tempVar25->Spell = Spell::FireBang;
            tempVar25->Icon = 22;
            tempVar25->Level1 = 22;
            tempVar25->Level2 = 25;
            tempVar25->Level3 = 28;
            tempVar25->Need1 = 3000;
            tempVar25->Need2 = 5000;
            tempVar25->Need3 = 10000;
            tempVar25->BaseCost = 14;
            tempVar25->LevelCost = 4;
            tempVar25->MPowerBase = 8;
            tempVar25->PowerBase = 8;
            tempVar25->Range = 9;
            MagicInfoList.push_back(tempVar25);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar25' statement was not added since tempVar25 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FireWall))
        {
            MagicInfo *tempVar26 = new MagicInfo();
            tempVar26->Name = "FireWall";
            tempVar26->Spell = Spell::FireWall;
            tempVar26->Icon = 21;
            tempVar26->Level1 = 24;
            tempVar26->Level2 = 28;
            tempVar26->Level3 = 33;
            tempVar26->Need1 = 4000;
            tempVar26->Need2 = 10000;
            tempVar26->Need3 = 20000;
            tempVar26->BaseCost = 30;
            tempVar26->LevelCost = 5;
            tempVar26->MPowerBase = 3;
            tempVar26->PowerBase = 3;
            tempVar26->Range = 9;
            MagicInfoList.push_back(tempVar26);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar26' statement was not added since tempVar26 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Lightning))
        {
            MagicInfo *tempVar27 = new MagicInfo();
            tempVar27->Name = "Lightning";
            tempVar27->Spell = Spell::Lightning;
            tempVar27->Icon = 9;
            tempVar27->Level1 = 26;
            tempVar27->Level2 = 29;
            tempVar27->Level3 = 32;
            tempVar27->Need1 = 3000;
            tempVar27->Need2 = 6000;
            tempVar27->Need3 = 12000;
            tempVar27->BaseCost = 38;
            tempVar27->LevelCost = 7;
            tempVar27->MPowerBase = 12;
            tempVar27->PowerBase = 12;
            tempVar27->Range = 0;
            MagicInfoList.push_back(tempVar27);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar27' statement was not added since tempVar27 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FrostCrunch))
        {
            MagicInfo *tempVar28 = new MagicInfo();
            tempVar28->Name = "FrostCrunch";
            tempVar28->Spell = Spell::FrostCrunch;
            tempVar28->Icon = 38;
            tempVar28->Level1 = 28;
            tempVar28->Level2 = 30;
            tempVar28->Level3 = 33;
            tempVar28->Need1 = 3000;
            tempVar28->Need2 = 5000;
            tempVar28->Need3 = 8000;
            tempVar28->BaseCost = 15;
            tempVar28->LevelCost = 3;
            tempVar28->MPowerBase = 12;
            tempVar28->PowerBase = 12;
            tempVar28->Range = 9;
            MagicInfoList.push_back(tempVar28);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar28' statement was not added since tempVar28 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ThunderStorm))
        {
            MagicInfo *tempVar29 = new MagicInfo();
            tempVar29->Name = "ThunderStorm";
            tempVar29->Spell = Spell::ThunderStorm;
            tempVar29->Icon = 23;
            tempVar29->Level1 = 30;
            tempVar29->Level2 = 32;
            tempVar29->Level3 = 34;
            tempVar29->Need1 = 4000;
            tempVar29->Need2 = 8000;
            tempVar29->Need3 = 12000;
            tempVar29->BaseCost = 29;
            tempVar29->LevelCost = 9;
            tempVar29->MPowerBase = 10;
            tempVar29->MPowerBonus = 20;
            tempVar29->PowerBase = 10;
            tempVar29->PowerBonus = 20;
            tempVar29->Range = 0;
            MagicInfoList.push_back(tempVar29);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar29' statement was not added since tempVar29 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MagicShield))
        {
            MagicInfo *tempVar30 = new MagicInfo();
            tempVar30->Name = "MagicShield";
            tempVar30->Spell = Spell::MagicShield;
            tempVar30->Icon = 30;
            tempVar30->Level1 = 31;
            tempVar30->Level2 = 34;
            tempVar30->Level3 = 38;
            tempVar30->Need1 = 3000;
            tempVar30->Need2 = 7000;
            tempVar30->Need3 = 10000;
            tempVar30->BaseCost = 35;
            tempVar30->LevelCost = 5;
            tempVar30->Range = 0;
            MagicInfoList.push_back(tempVar30);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar30' statement was not added since tempVar30 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::TurnUndead))
        {
            MagicInfo *tempVar31 = new MagicInfo();
            tempVar31->Name = "TurnUndead";
            tempVar31->Spell = Spell::TurnUndead;
            tempVar31->Icon = 31;
            tempVar31->Level1 = 32;
            tempVar31->Level2 = 35;
            tempVar31->Level3 = 39;
            tempVar31->Need1 = 3000;
            tempVar31->Need2 = 7000;
            tempVar31->Need3 = 10000;
            tempVar31->BaseCost = 52;
            tempVar31->LevelCost = 13;
            tempVar31->Range = 9;
            MagicInfoList.push_back(tempVar31);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar31' statement was not added since tempVar31 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Vampirism))
        {
            MagicInfo *tempVar32 = new MagicInfo();
            tempVar32->Name = "Vampirism";
            tempVar32->Spell = Spell::Vampirism;
            tempVar32->Icon = 47;
            tempVar32->Level1 = 33;
            tempVar32->Level2 = 36;
            tempVar32->Level3 = 40;
            tempVar32->Need1 = 3000;
            tempVar32->Need2 = 5000;
            tempVar32->Need3 = 8000;
            tempVar32->BaseCost = 26;
            tempVar32->LevelCost = 13;
            tempVar32->MPowerBase = 12;
            tempVar32->PowerBase = 12;
            tempVar32->Range = 9;
            MagicInfoList.push_back(tempVar32);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar32' statement was not added since tempVar32 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::IceStorm))
        {
            MagicInfo *tempVar33 = new MagicInfo();
            tempVar33->Name = "IceStorm";
            tempVar33->Spell = Spell::IceStorm;
            tempVar33->Icon = 32;
            tempVar33->Level1 = 35;
            tempVar33->Level2 = 37;
            tempVar33->Level3 = 40;
            tempVar33->Need1 = 4000;
            tempVar33->Need2 = 8000;
            tempVar33->Need3 = 12000;
            tempVar33->BaseCost = 33;
            tempVar33->LevelCost = 3;
            tempVar33->MPowerBase = 12;
            tempVar33->PowerBase = 14;
            tempVar33->Range = 9;
            MagicInfoList.push_back(tempVar33);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar33' statement was not added since tempVar33 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FlameDisruptor))
        {
            MagicInfo *tempVar34 = new MagicInfo();
            tempVar34->Name = "FlameDisruptor";
            tempVar34->Spell = Spell::FlameDisruptor;
            tempVar34->Icon = 34;
            tempVar34->Level1 = 38;
            tempVar34->Level2 = 40;
            tempVar34->Level3 = 42;
            tempVar34->Need1 = 5000;
            tempVar34->Need2 = 9000;
            tempVar34->Need3 = 14000;
            tempVar34->BaseCost = 28;
            tempVar34->LevelCost = 3;
            tempVar34->MPowerBase = 15;
            tempVar34->MPowerBonus = 20;
            tempVar34->PowerBase = 9;
            tempVar34->Range = 9;
            MagicInfoList.push_back(tempVar34);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar34' statement was not added since tempVar34 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Mirroring))
        {
            MagicInfo *tempVar35 = new MagicInfo();
            tempVar35->Name = "Mirroring";
            tempVar35->Spell = Spell::Mirroring;
            tempVar35->Icon = 41;
            tempVar35->Level1 = 41;
            tempVar35->Level2 = 43;
            tempVar35->Level3 = 45;
            tempVar35->Need1 = 6000;
            tempVar35->Need2 = 11000;
            tempVar35->Need3 = 16000;
            tempVar35->BaseCost = 21;
            tempVar35->Range = 0;
            MagicInfoList.push_back(tempVar35);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar35' statement was not added since tempVar35 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FlameField))
        {
            MagicInfo *tempVar36 = new MagicInfo();
            tempVar36->Name = "FlameField";
            tempVar36->Spell = Spell::FlameField;
            tempVar36->Icon = 44;
            tempVar36->Level1 = 42;
            tempVar36->Level2 = 43;
            tempVar36->Level3 = 45;
            tempVar36->Need1 = 6000;
            tempVar36->Need2 = 11000;
            tempVar36->Need3 = 16000;
            tempVar36->BaseCost = 45;
            tempVar36->LevelCost = 8;
            tempVar36->MPowerBase = 100;
            tempVar36->PowerBase = 25;
            tempVar36->Range = 9;
            MagicInfoList.push_back(tempVar36);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar36' statement was not added since tempVar36 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Blizzard))
        {
            MagicInfo *tempVar37 = new MagicInfo();
            tempVar37->Name = "Blizzard";
            tempVar37->Spell = Spell::Blizzard;
            tempVar37->Icon = 51;
            tempVar37->Level1 = 44;
            tempVar37->Level2 = 47;
            tempVar37->Level3 = 50;
            tempVar37->Need1 = 8000;
            tempVar37->Need2 = 16000;
            tempVar37->Need3 = 24000;
            tempVar37->BaseCost = 65;
            tempVar37->LevelCost = 10;
            tempVar37->MPowerBase = 30;
            tempVar37->MPowerBonus = 10;
            tempVar37->PowerBase = 20;
            tempVar37->PowerBonus = 5;
            tempVar37->Range = 9;
            MagicInfoList.push_back(tempVar37);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar37' statement was not added since tempVar37 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MagicBooster))
        {
            MagicInfo *tempVar38 = new MagicInfo();
            tempVar38->Name = "MagicBooster";
            tempVar38->Spell = Spell::MagicBooster;
            tempVar38->Icon = 73;
            tempVar38->Level1 = 47;
            tempVar38->Level2 = 49;
            tempVar38->Level3 = 52;
            tempVar38->Need1 = 12000;
            tempVar38->Need2 = 18000;
            tempVar38->Need3 = 24000;
            tempVar38->BaseCost = 150;
            tempVar38->LevelCost = 15;
            tempVar38->Range = 0;
            MagicInfoList.push_back(tempVar38);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar38' statement was not added since tempVar38 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MeteorStrike))
        {
            MagicInfo *tempVar39 = new MagicInfo();
            tempVar39->Name = "MeteorStrike";
            tempVar39->Spell = Spell::MeteorStrike;
            tempVar39->Icon = 52;
            tempVar39->Level1 = 49;
            tempVar39->Level2 = 52;
            tempVar39->Level3 = 55;
            tempVar39->Need1 = 15000;
            tempVar39->Need2 = 20000;
            tempVar39->Need3 = 25000;
            tempVar39->BaseCost = 115;
            tempVar39->LevelCost = 17;
            tempVar39->MPowerBase = 40;
            tempVar39->MPowerBonus = 10;
            tempVar39->PowerBase = 20;
            tempVar39->PowerBonus = 15;
            tempVar39->Range = 9;
            MagicInfoList.push_back(tempVar39);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar39' statement was not added since tempVar39 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::IceThrust))
        {
            MagicInfo *tempVar40 = new MagicInfo();
            tempVar40->Name = "IceThrust";
            tempVar40->Spell = Spell::IceThrust;
            tempVar40->Icon = 56;
            tempVar40->Level1 = 53;
            tempVar40->Level2 = 56;
            tempVar40->Level3 = 59;
            tempVar40->Need1 = 17000;
            tempVar40->Need2 = 22000;
            tempVar40->Need3 = 27000;
            tempVar40->BaseCost = 100;
            tempVar40->LevelCost = 20;
            tempVar40->MPowerBase = 100;
            tempVar40->PowerBase = 50;
            tempVar40->Range = 0;
            MagicInfoList.push_back(tempVar40);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar40' statement was not added since tempVar40 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Blink))
        {
            MagicInfo *tempVar41 = new MagicInfo();
            tempVar41->Name = "Blink";
            tempVar41->Spell = Spell::Blink;
            tempVar41->Icon = 20;
            tempVar41->Level1 = 19;
            tempVar41->Level2 = 22;
            tempVar41->Level3 = 25;
            tempVar41->Need1 = 350;
            tempVar41->Need2 = 1000;
            tempVar41->Need3 = 2000;
            tempVar41->BaseCost = 10;
            tempVar41->LevelCost = 3;
            tempVar41->Range = 9;
            MagicInfoList.push_back(tempVar41);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar41' statement was not added since tempVar41 was passed to a method or constructor. Handle memory management manually.
        }
        //if (!MagicExists(Spell.FastMove)) MagicInfoList.Add(new MagicInfo { Name = "FastMove", Spell = Spell.ImmortalSkin, Icon = ?, Level1 = ?, Level2 = ?, Level3 = ?, Need1 = ?, Need2 = ?, Need3 = ?, BaseCost = ?, LevelCost = ?, DelayBase = ?, DelayReduction = ? });
        if (!MagicExists(Spell::StormEscape))
        {
            MagicInfo *tempVar42 = new MagicInfo();
            tempVar42->Name = "StormEscape";
            tempVar42->Spell = Spell::StormEscape;
            tempVar42->Icon = 23;
            tempVar42->Level1 = 60;
            tempVar42->Level2 = 61;
            tempVar42->Level3 = 62;
            tempVar42->Need1 = 2200;
            tempVar42->Need2 = 3300;
            tempVar42->Need3 = 4400;
            tempVar42->BaseCost = 65;
            tempVar42->LevelCost = 8;
            tempVar42->MPowerBase = 12;
            tempVar42->PowerBase = 4;
            tempVar42->Range = 9;
            MagicInfoList.push_back(tempVar42);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar42' statement was not added since tempVar42 was passed to a method or constructor. Handle memory management manually.
        }


        //Taoist
        if (!MagicExists(Spell::Healing))
        {
            MagicInfo *tempVar43 = new MagicInfo();
            tempVar43->Name = "Healing";
            tempVar43->Spell = Spell::Healing;
            tempVar43->Icon = 1;
            tempVar43->Level1 = 7;
            tempVar43->Level2 = 11;
            tempVar43->Level3 = 14;
            tempVar43->Need1 = 150;
            tempVar43->Need2 = 350;
            tempVar43->Need3 = 700;
            tempVar43->BaseCost = 3;
            tempVar43->LevelCost = 2;
            tempVar43->MPowerBase = 14;
            tempVar43->Range = 9;
            MagicInfoList.push_back(tempVar43);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar43' statement was not added since tempVar43 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SpiritSword))
        {
            MagicInfo *tempVar44 = new MagicInfo();
            tempVar44->Name = "SpiritSword";
            tempVar44->Spell = Spell::SpiritSword;
            tempVar44->Icon = 3;
            tempVar44->Level1 = 9;
            tempVar44->Level2 = 12;
            tempVar44->Level3 = 15;
            tempVar44->Need1 = 350;
            tempVar44->Need2 = 1300;
            tempVar44->Need3 = 2700;
            tempVar44->Range = 0;
            MagicInfoList.push_back(tempVar44);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar44' statement was not added since tempVar44 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Poisoning))
        {
            MagicInfo *tempVar45 = new MagicInfo();
            tempVar45->Name = "Poisoning";
            tempVar45->Spell = Spell::Poisoning;
            tempVar45->Icon = 5;
            tempVar45->Level1 = 14;
            tempVar45->Level2 = 17;
            tempVar45->Level3 = 20;
            tempVar45->Need1 = 700;
            tempVar45->Need2 = 1300;
            tempVar45->Need3 = 2700;
            tempVar45->BaseCost = 2;
            tempVar45->LevelCost = 1;
            tempVar45->Range = 9;
            MagicInfoList.push_back(tempVar45);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar45' statement was not added since tempVar45 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SoulFireBall))
        {
            MagicInfo *tempVar46 = new MagicInfo();
            tempVar46->Name = "SoulFireBall";
            tempVar46->Spell = Spell::SoulFireBall;
            tempVar46->Icon = 12;
            tempVar46->Level1 = 18;
            tempVar46->Level2 = 21;
            tempVar46->Level3 = 24;
            tempVar46->Need1 = 1300;
            tempVar46->Need2 = 2700;
            tempVar46->Need3 = 4000;
            tempVar46->BaseCost = 3;
            tempVar46->LevelCost = 1;
            tempVar46->MPowerBase = 8;
            tempVar46->PowerBase = 3;
            tempVar46->Range = 9;
            MagicInfoList.push_back(tempVar46);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar46' statement was not added since tempVar46 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonSkeleton))
        {
            MagicInfo *tempVar47 = new MagicInfo();
            tempVar47->Name = "SummonSkeleton";
            tempVar47->Spell = Spell::SummonSkeleton;
            tempVar47->Icon = 16;
            tempVar47->Level1 = 19;
            tempVar47->Level2 = 22;
            tempVar47->Level3 = 26;
            tempVar47->Need1 = 1000;
            tempVar47->Need2 = 2000;
            tempVar47->Need3 = 3500;
            tempVar47->BaseCost = 12;
            tempVar47->LevelCost = 4;
            tempVar47->Range = 0;
            MagicInfoList.push_back(tempVar47);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar47' statement was not added since tempVar47 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Hiding))
        {
            MagicInfo *tempVar48 = new MagicInfo();
            tempVar48->Name = "Hiding";
            tempVar48->Spell = Spell::Hiding;
            tempVar48->Icon = 17;
            tempVar48->Level1 = 20;
            tempVar48->Level2 = 23;
            tempVar48->Level3 = 26;
            tempVar48->Need1 = 1300;
            tempVar48->Need2 = 2700;
            tempVar48->Need3 = 5300;
            tempVar48->BaseCost = 1;
            tempVar48->LevelCost = 1;
            tempVar48->Range = 0;
            MagicInfoList.push_back(tempVar48);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar48' statement was not added since tempVar48 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MassHiding))
        {
            MagicInfo *tempVar49 = new MagicInfo();
            tempVar49->Name = "MassHiding";
            tempVar49->Spell = Spell::MassHiding;
            tempVar49->Icon = 18;
            tempVar49->Level1 = 21;
            tempVar49->Level2 = 25;
            tempVar49->Level3 = 29;
            tempVar49->Need1 = 1300;
            tempVar49->Need2 = 2700;
            tempVar49->Need3 = 5300;
            tempVar49->BaseCost = 2;
            tempVar49->LevelCost = 2;
            tempVar49->Range = 9;
            MagicInfoList.push_back(tempVar49);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar49' statement was not added since tempVar49 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SoulShield))
        {
            MagicInfo *tempVar50 = new MagicInfo();
            tempVar50->Name = "SoulShield";
            tempVar50->Spell = Spell::SoulShield;
            tempVar50->Icon = 13;
            tempVar50->Level1 = 22;
            tempVar50->Level2 = 24;
            tempVar50->Level3 = 26;
            tempVar50->Need1 = 2000;
            tempVar50->Need2 = 3500;
            tempVar50->Need3 = 7000;
            tempVar50->BaseCost = 2;
            tempVar50->LevelCost = 2;
            tempVar50->Range = 9;
            MagicInfoList.push_back(tempVar50);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar50' statement was not added since tempVar50 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Revelation))
        {
            MagicInfo *tempVar51 = new MagicInfo();
            tempVar51->Name = "Revelation";
            tempVar51->Spell = Spell::Revelation;
            tempVar51->Icon = 27;
            tempVar51->Level1 = 23;
            tempVar51->Level2 = 25;
            tempVar51->Level3 = 28;
            tempVar51->Need1 = 1500;
            tempVar51->Need2 = 2500;
            tempVar51->Need3 = 4000;
            tempVar51->BaseCost = 4;
            tempVar51->LevelCost = 4;
            tempVar51->Range = 9;
            MagicInfoList.push_back(tempVar51);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar51' statement was not added since tempVar51 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::BlessedArmour))
        {
            MagicInfo *tempVar52 = new MagicInfo();
            tempVar52->Name = "BlessedArmour";
            tempVar52->Spell = Spell::BlessedArmour;
            tempVar52->Icon = 14;
            tempVar52->Level1 = 25;
            tempVar52->Level2 = 27;
            tempVar52->Level3 = 29;
            tempVar52->Need1 = 4000;
            tempVar52->Need2 = 6000;
            tempVar52->Need3 = 10000;
            tempVar52->BaseCost = 2;
            tempVar52->LevelCost = 2;
            tempVar52->Range = 9;
            MagicInfoList.push_back(tempVar52);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar52' statement was not added since tempVar52 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::EnergyRepulsor))
        {
            MagicInfo *tempVar53 = new MagicInfo();
            tempVar53->Name = "EnergyRepulsor";
            tempVar53->Spell = Spell::EnergyRepulsor;
            tempVar53->Icon = 36;
            tempVar53->Level1 = 27;
            tempVar53->Level2 = 29;
            tempVar53->Level3 = 31;
            tempVar53->Need1 = 1800;
            tempVar53->Need2 = 2400;
            tempVar53->Need3 = 3200;
            tempVar53->BaseCost = 2;
            tempVar53->LevelCost = 2;
            tempVar53->Range = 0;
            tempVar53->MPowerBase = 4;
            MagicInfoList.push_back(tempVar53);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar53' statement was not added since tempVar53 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::TrapHexagon))
        {
            MagicInfo *tempVar54 = new MagicInfo();
            tempVar54->Name = "TrapHexagon";
            tempVar54->Spell = Spell::TrapHexagon;
            tempVar54->Icon = 15;
            tempVar54->Level1 = 28;
            tempVar54->Level2 = 30;
            tempVar54->Level3 = 32;
            tempVar54->Need1 = 2500;
            tempVar54->Need2 = 5000;
            tempVar54->Need3 = 10000;
            tempVar54->BaseCost = 7;
            tempVar54->LevelCost = 3;
            tempVar54->Range = 9;
            MagicInfoList.push_back(tempVar54);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar54' statement was not added since tempVar54 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Purification))
        {
            MagicInfo *tempVar55 = new MagicInfo();
            tempVar55->Name = "Purification";
            tempVar55->Spell = Spell::Purification;
            tempVar55->Icon = 39;
            tempVar55->Level1 = 30;
            tempVar55->Level2 = 32;
            tempVar55->Level3 = 35;
            tempVar55->Need1 = 3000;
            tempVar55->Need2 = 5000;
            tempVar55->Need3 = 8000;
            tempVar55->BaseCost = 14;
            tempVar55->LevelCost = 2;
            tempVar55->Range = 9;
            MagicInfoList.push_back(tempVar55);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar55' statement was not added since tempVar55 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MassHealing))
        {
            MagicInfo *tempVar56 = new MagicInfo();
            tempVar56->Name = "MassHealing";
            tempVar56->Spell = Spell::MassHealing;
            tempVar56->Icon = 28;
            tempVar56->Level1 = 31;
            tempVar56->Level2 = 33;
            tempVar56->Level3 = 36;
            tempVar56->Need1 = 2000;
            tempVar56->Need2 = 4000;
            tempVar56->Need3 = 8000;
            tempVar56->BaseCost = 28;
            tempVar56->LevelCost = 3;
            tempVar56->MPowerBase = 10;
            tempVar56->PowerBase = 4;
            tempVar56->Range = 9;
            MagicInfoList.push_back(tempVar56);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar56' statement was not added since tempVar56 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Hallucination))
        {
            MagicInfo *tempVar57 = new MagicInfo();
            tempVar57->Name = "Hallucination";
            tempVar57->Spell = Spell::Hallucination;
            tempVar57->Icon = 48;
            tempVar57->Level1 = 31;
            tempVar57->Level2 = 34;
            tempVar57->Level3 = 36;
            tempVar57->Need1 = 4000;
            tempVar57->Need2 = 6000;
            tempVar57->Need3 = 9000;
            tempVar57->BaseCost = 22;
            tempVar57->LevelCost = 10;
            tempVar57->Range = 9;
            MagicInfoList.push_back(tempVar57);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar57' statement was not added since tempVar57 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::UltimateEnhancer))
        {
            MagicInfo *tempVar58 = new MagicInfo();
            tempVar58->Name = "UltimateEnchancer";
            tempVar58->Spell = Spell::UltimateEnhancer;
            tempVar58->Icon = 35;
            tempVar58->Level1 = 33;
            tempVar58->Level2 = 35;
            tempVar58->Level3 = 38;
            tempVar58->Need1 = 5000;
            tempVar58->Need2 = 7000;
            tempVar58->Need3 = 10000;
            tempVar58->BaseCost = 28;
            tempVar58->LevelCost = 4;
            tempVar58->Range = 9;
            MagicInfoList.push_back(tempVar58);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar58' statement was not added since tempVar58 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonShinsu))
        {
            MagicInfo *tempVar59 = new MagicInfo();
            tempVar59->Name = "SummonShinsu";
            tempVar59->Spell = Spell::SummonShinsu;
            tempVar59->Icon = 29;
            tempVar59->Level1 = 35;
            tempVar59->Level2 = 37;
            tempVar59->Level3 = 40;
            tempVar59->Need1 = 2000;
            tempVar59->Need2 = 4000;
            tempVar59->Need3 = 6000;
            tempVar59->BaseCost = 28;
            tempVar59->LevelCost = 4;
            tempVar59->Range = 0;
            MagicInfoList.push_back(tempVar59);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar59' statement was not added since tempVar59 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Reincarnation))
        {
            MagicInfo *tempVar60 = new MagicInfo();
            tempVar60->Name = "Reincarnation";
            tempVar60->Spell = Spell::Reincarnation;
            tempVar60->Icon = 53;
            tempVar60->Level1 = 37;
            tempVar60->Level2 = 39;
            tempVar60->Level3 = 41;
            tempVar60->Need1 = 2000;
            tempVar60->Need2 = 6000;
            tempVar60->Need3 = 10000;
            tempVar60->BaseCost = 125;
            tempVar60->LevelCost = 17;
            tempVar60->Range = 9;
            MagicInfoList.push_back(tempVar60);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar60' statement was not added since tempVar60 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonHolyDeva))
        {
            MagicInfo *tempVar61 = new MagicInfo();
            tempVar61->Name = "SummonHolyDeva";
            tempVar61->Spell = Spell::SummonHolyDeva;
            tempVar61->Icon = 40;
            tempVar61->Level1 = 38;
            tempVar61->Level2 = 41;
            tempVar61->Level3 = 43;
            tempVar61->Need1 = 4000;
            tempVar61->Need2 = 6000;
            tempVar61->Need3 = 9000;
            tempVar61->BaseCost = 28;
            tempVar61->LevelCost = 4;
            tempVar61->Range = 0;
            MagicInfoList.push_back(tempVar61);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar61' statement was not added since tempVar61 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Curse))
        {
            MagicInfo *tempVar62 = new MagicInfo();
            tempVar62->Name = "Curse";
            tempVar62->Spell = Spell::Curse;
            tempVar62->Icon = 45;
            tempVar62->Level1 = 40;
            tempVar62->Level2 = 42;
            tempVar62->Level3 = 44;
            tempVar62->Need1 = 4000;
            tempVar62->Need2 = 6000;
            tempVar62->Need3 = 9000;
            tempVar62->BaseCost = 17;
            tempVar62->LevelCost = 3;
            tempVar62->Range = 9;
            tempVar62->MPowerBase = 20;
            MagicInfoList.push_back(tempVar62);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar62' statement was not added since tempVar62 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Plague))
        {
            MagicInfo *tempVar63 = new MagicInfo();
            tempVar63->Name = "Plague";
            tempVar63->Spell = Spell::Plague;
            tempVar63->Icon = 74;
            tempVar63->Level1 = 42;
            tempVar63->Level2 = 44;
            tempVar63->Level3 = 47;
            tempVar63->Need1 = 5000;
            tempVar63->Need2 = 9000;
            tempVar63->Need3 = 13000;
            tempVar63->BaseCost = 20;
            tempVar63->LevelCost = 5;
            tempVar63->Range = 9;
            MagicInfoList.push_back(tempVar63);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar63' statement was not added since tempVar63 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::PoisonCloud))
        {
            MagicInfo *tempVar64 = new MagicInfo();
            tempVar64->Name = "PoisonCloud";
            tempVar64->Spell = Spell::PoisonCloud;
            tempVar64->Icon = 54;
            tempVar64->Level1 = 43;
            tempVar64->Level2 = 45;
            tempVar64->Level3 = 48;
            tempVar64->Need1 = 4000;
            tempVar64->Need2 = 8000;
            tempVar64->Need3 = 12000;
            tempVar64->BaseCost = 30;
            tempVar64->LevelCost = 5;
            tempVar64->MPowerBase = 40;
            tempVar64->PowerBase = 20;
            tempVar64->DelayBase = 18000;
            tempVar64->DelayReduction = 2000;
            tempVar64->Range = 9;
            MagicInfoList.push_back(tempVar64);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar64' statement was not added since tempVar64 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::EnergyShield))
        {
            MagicInfo *tempVar65 = new MagicInfo();
            tempVar65->Name = "EnergyShield";
            tempVar65->Spell = Spell::EnergyShield;
            tempVar65->Icon = 57;
            tempVar65->Level1 = 48;
            tempVar65->Level2 = 51;
            tempVar65->Level3 = 54;
            tempVar65->Need1 = 5000;
            tempVar65->Need2 = 9000;
            tempVar65->Need3 = 13000;
            tempVar65->BaseCost = 50;
            tempVar65->LevelCost = 20;
            tempVar65->Range = 9;
            MagicInfoList.push_back(tempVar65);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar65' statement was not added since tempVar65 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::PetEnhancer))
        {
            MagicInfo *tempVar66 = new MagicInfo();
            tempVar66->Name = "PetEnhancer";
            tempVar66->Spell = Spell::PetEnhancer;
            tempVar66->Icon = 78;
            tempVar66->Level1 = 45;
            tempVar66->Level2 = 48;
            tempVar66->Level3 = 51;
            tempVar66->Need1 = 4000;
            tempVar66->Need2 = 8000;
            tempVar66->Need3 = 12000;
            tempVar66->BaseCost = 30;
            tempVar66->LevelCost = 40;
            tempVar66->Range = 0;
            MagicInfoList.push_back(tempVar66);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar66' statement was not added since tempVar66 was passed to a method or constructor. Handle memory management manually.
        }
        //if (!MagicExists(Spell.HealingCircle)) MagicInfoList.Add(new MagicInfo { Name = "HealingCircle", Spell = Spell.ImmortalSkin, Icon = ?, Level1 = ?, Level2 = ?, Level3 = ?, Need1 = ?, Need2 = ?, Need3 = ?, BaseCost = ?, LevelCost = ?, DelayBase = ?, DelayReduction = ? });

        //Assassin
        if (!MagicExists(Spell::FatalSword))
        {
            MagicInfo *tempVar67 = new MagicInfo();
            tempVar67->Name = "FatalSword";
            tempVar67->Spell = Spell::FatalSword;
            tempVar67->Icon = 58;
            tempVar67->Level1 = 7;
            tempVar67->Level2 = 9;
            tempVar67->Level3 = 12;
            tempVar67->Need1 = 500;
            tempVar67->Need2 = 1000;
            tempVar67->Need3 = 2300;
            tempVar67->Range = 0;
            MagicInfoList.push_back(tempVar67);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar67' statement was not added since tempVar67 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::DoubleSlash))
        {
            MagicInfo *tempVar68 = new MagicInfo();
            tempVar68->Name = "DoubleSlash";
            tempVar68->Spell = Spell::DoubleSlash;
            tempVar68->Icon = 59;
            tempVar68->Level1 = 15;
            tempVar68->Level2 = 17;
            tempVar68->Level3 = 19;
            tempVar68->Need1 = 700;
            tempVar68->Need2 = 1500;
            tempVar68->Need3 = 2200;
            tempVar68->BaseCost = 2;
            tempVar68->LevelCost = 1;
            MagicInfoList.push_back(tempVar68);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar68' statement was not added since tempVar68 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Haste))
        {
            MagicInfo *tempVar69 = new MagicInfo();
            tempVar69->Name = "Haste";
            tempVar69->Spell = Spell::Haste;
            tempVar69->Icon = 60;
            tempVar69->Level1 = 20;
            tempVar69->Level2 = 22;
            tempVar69->Level3 = 25;
            tempVar69->Need1 = 2000;
            tempVar69->Need2 = 3000;
            tempVar69->Need3 = 6000;
            tempVar69->BaseCost = 3;
            tempVar69->LevelCost = 2;
            tempVar69->Range = 0;
            MagicInfoList.push_back(tempVar69);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar69' statement was not added since tempVar69 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FlashDash))
        {
            MagicInfo *tempVar70 = new MagicInfo();
            tempVar70->Name = "FlashDash";
            tempVar70->Spell = Spell::FlashDash;
            tempVar70->Icon = 61;
            tempVar70->Level1 = 25;
            tempVar70->Level2 = 27;
            tempVar70->Level3 = 30;
            tempVar70->Need1 = 4000;
            tempVar70->Need2 = 7000;
            tempVar70->Need3 = 9000;
            tempVar70->BaseCost = 12;
            tempVar70->LevelCost = 2;
            tempVar70->DelayBase = 200;
            tempVar70->Range = 0;
            MagicInfoList.push_back(tempVar70);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar70' statement was not added since tempVar70 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::LightBody))
        {
            MagicInfo *tempVar71 = new MagicInfo();
            tempVar71->Name = "LightBody";
            tempVar71->Spell = Spell::LightBody;
            tempVar71->Icon = 68;
            tempVar71->Level1 = 27;
            tempVar71->Level2 = 29;
            tempVar71->Level3 = 32;
            tempVar71->Need1 = 5000;
            tempVar71->Need2 = 7000;
            tempVar71->Need3 = 10000;
            tempVar71->BaseCost = 11;
            tempVar71->LevelCost = 2;
            tempVar71->Range = 0;
            MagicInfoList.push_back(tempVar71);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar71' statement was not added since tempVar71 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::HeavenlySword))
        {
            MagicInfo *tempVar72 = new MagicInfo();
            tempVar72->Name = "HeavenlySword";
            tempVar72->Spell = Spell::HeavenlySword;
            tempVar72->Icon = 62;
            tempVar72->Level1 = 30;
            tempVar72->Level2 = 32;
            tempVar72->Level3 = 35;
            tempVar72->Need1 = 4000;
            tempVar72->Need2 = 8000;
            tempVar72->Need3 = 10000;
            tempVar72->BaseCost = 13;
            tempVar72->LevelCost = 2;
            tempVar72->MPowerBase = 8;
            tempVar72->Range = 0;
            MagicInfoList.push_back(tempVar72);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar72' statement was not added since tempVar72 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FireBurst))
        {
            MagicInfo *tempVar73 = new MagicInfo();
            tempVar73->Name = "FireBurst";
            tempVar73->Spell = Spell::FireBurst;
            tempVar73->Icon = 63;
            tempVar73->Level1 = 33;
            tempVar73->Level2 = 35;
            tempVar73->Level3 = 38;
            tempVar73->Need1 = 4000;
            tempVar73->Need2 = 6000;
            tempVar73->Need3 = 8000;
            tempVar73->BaseCost = 10;
            tempVar73->LevelCost = 1;
            tempVar73->Range = 0;
            MagicInfoList.push_back(tempVar73);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar73' statement was not added since tempVar73 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Trap))
        {
            MagicInfo *tempVar74 = new MagicInfo();
            tempVar74->Name = "Trap";
            tempVar74->Spell = Spell::Trap;
            tempVar74->Icon = 64;
            tempVar74->Level1 = 33;
            tempVar74->Level2 = 35;
            tempVar74->Level3 = 38;
            tempVar74->Need1 = 2000;
            tempVar74->Need2 = 4000;
            tempVar74->Need3 = 6000;
            tempVar74->BaseCost = 14;
            tempVar74->LevelCost = 2;
            tempVar74->DelayBase = 60000;
            tempVar74->DelayReduction = 15000;
            tempVar74->Range = 9;
            MagicInfoList.push_back(tempVar74);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar74' statement was not added since tempVar74 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::PoisonSword))
        {
            MagicInfo *tempVar75 = new MagicInfo();
            tempVar75->Name = "PoisonSword";
            tempVar75->Spell = Spell::PoisonSword;
            tempVar75->Icon = 69;
            tempVar75->Level1 = 34;
            tempVar75->Level2 = 36;
            tempVar75->Level3 = 39;
            tempVar75->Need1 = 5000;
            tempVar75->Need2 = 8000;
            tempVar75->Need3 = 11000;
            tempVar75->BaseCost = 14;
            tempVar75->LevelCost = 3;
            tempVar75->Range = 0;
            MagicInfoList.push_back(tempVar75);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar75' statement was not added since tempVar75 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MoonLight))
        {
            MagicInfo *tempVar76 = new MagicInfo();
            tempVar76->Name = "MoonLight";
            tempVar76->Spell = Spell::MoonLight;
            tempVar76->Icon = 65;
            tempVar76->Level1 = 36;
            tempVar76->Level2 = 39;
            tempVar76->Level3 = 42;
            tempVar76->Need1 = 3000;
            tempVar76->Need2 = 5000;
            tempVar76->Need3 = 8000;
            tempVar76->BaseCost = 36;
            tempVar76->LevelCost = 3;
            tempVar76->Range = 0;
            MagicInfoList.push_back(tempVar76);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar76' statement was not added since tempVar76 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MPEater))
        {
            MagicInfo *tempVar77 = new MagicInfo();
            tempVar77->Name = "MPEater";
            tempVar77->Spell = Spell::MPEater;
            tempVar77->Icon = 66;
            tempVar77->Level1 = 38;
            tempVar77->Level2 = 41;
            tempVar77->Level3 = 44;
            tempVar77->Need1 = 5000;
            tempVar77->Need2 = 8000;
            tempVar77->Need3 = 11000;
            tempVar77->Range = 0;
            MagicInfoList.push_back(tempVar77);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar77' statement was not added since tempVar77 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SwiftFeet))
        {
            MagicInfo *tempVar78 = new MagicInfo();
            tempVar78->Name = "SwiftFeet";
            tempVar78->Spell = Spell::SwiftFeet;
            tempVar78->Icon = 67;
            tempVar78->Level1 = 40;
            tempVar78->Level2 = 43;
            tempVar78->Level3 = 46;
            tempVar78->Need1 = 4000;
            tempVar78->Need2 = 6000;
            tempVar78->Need3 = 9000;
            tempVar78->BaseCost = 17;
            tempVar78->LevelCost = 5;
            tempVar78->DelayBase = 210000;
            tempVar78->DelayReduction = 40000;
            tempVar78->Range = 0;
            MagicInfoList.push_back(tempVar78);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar78' statement was not added since tempVar78 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::DarkBody))
        {
            MagicInfo *tempVar79 = new MagicInfo();
            tempVar79->Name = "DarkBody";
            tempVar79->Spell = Spell::DarkBody;
            tempVar79->Icon = 70;
            tempVar79->Level1 = 46;
            tempVar79->Level2 = 49;
            tempVar79->Level3 = 52;
            tempVar79->Need1 = 6000;
            tempVar79->Need2 = 10000;
            tempVar79->Need3 = 14000;
            tempVar79->BaseCost = 40;
            tempVar79->LevelCost = 7;
            tempVar79->Range = 0;
            MagicInfoList.push_back(tempVar79);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar79' statement was not added since tempVar79 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Hemorrhage))
        {
            MagicInfo *tempVar80 = new MagicInfo();
            tempVar80->Name = "Hemorrhage";
            tempVar80->Spell = Spell::Hemorrhage;
            tempVar80->Icon = 75;
            tempVar80->Level1 = 47;
            tempVar80->Level2 = 51;
            tempVar80->Level3 = 55;
            tempVar80->Need1 = 9000;
            tempVar80->Need2 = 15000;
            tempVar80->Need3 = 21000;
            tempVar80->Range = 0;
            MagicInfoList.push_back(tempVar80);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar80' statement was not added since tempVar80 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::CrescentSlash))
        {
            MagicInfo *tempVar81 = new MagicInfo();
            tempVar81->Name = "CresentSlash";
            tempVar81->Spell = Spell::CrescentSlash;
            tempVar81->Icon = 71;
            tempVar81->Level1 = 50;
            tempVar81->Level2 = 53;
            tempVar81->Level3 = 56;
            tempVar81->Need1 = 12000;
            tempVar81->Need2 = 16000;
            tempVar81->Need3 = 24000;
            tempVar81->BaseCost = 19;
            tempVar81->LevelCost = 5;
            tempVar81->Range = 0;
            MagicInfoList.push_back(tempVar81);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar81' statement was not added since tempVar81 was passed to a method or constructor. Handle memory management manually.
        }
        //if (!MagicExists(Spell.MoonMist)) MagicInfoList.Add(new MagicInfo { Name = "MoonMist", Spell = Spell.ImmortalSkin, Icon = ?, Level1 = ?, Level2 = ?, Level3 = ?, Need1 = ?, Need2 = ?, Need3 = ?, BaseCost = ?, LevelCost = ?, DelayBase = ?, DelayReduction = ? });

        //Archer
        if (!MagicExists(Spell::Focus))
        {
            MagicInfo *tempVar82 = new MagicInfo();
            tempVar82->Name = "Focus";
            tempVar82->Spell = Spell::Focus;
            tempVar82->Icon = 88;
            tempVar82->Level1 = 7;
            tempVar82->Level2 = 13;
            tempVar82->Level3 = 17;
            tempVar82->Need1 = 270;
            tempVar82->Need2 = 600;
            tempVar82->Need3 = 1300;
            tempVar82->Range = 0;
            MagicInfoList.push_back(tempVar82);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar82' statement was not added since tempVar82 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::StraightShot))
        {
            MagicInfo *tempVar83 = new MagicInfo();
            tempVar83->Name = "StraightShot";
            tempVar83->Spell = Spell::StraightShot;
            tempVar83->Icon = 89;
            tempVar83->Level1 = 9;
            tempVar83->Level2 = 12;
            tempVar83->Level3 = 16;
            tempVar83->Need1 = 350;
            tempVar83->Need2 = 750;
            tempVar83->Need3 = 1400;
            tempVar83->BaseCost = 3;
            tempVar83->LevelCost = 2;
            tempVar83->MPowerBase = 8;
            tempVar83->PowerBase = 3;
            tempVar83->Range = 9;
            MagicInfoList.push_back(tempVar83);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar83' statement was not added since tempVar83 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::DoubleShot))
        {
            MagicInfo *tempVar84 = new MagicInfo();
            tempVar84->Name = "DoubleShot";
            tempVar84->Spell = Spell::DoubleShot;
            tempVar84->Icon = 90;
            tempVar84->Level1 = 14;
            tempVar84->Level2 = 18;
            tempVar84->Level3 = 21;
            tempVar84->Need1 = 700;
            tempVar84->Need2 = 1500;
            tempVar84->Need3 = 2100;
            tempVar84->BaseCost = 3;
            tempVar84->LevelCost = 2;
            tempVar84->MPowerBase = 6;
            tempVar84->PowerBase = 2;
            tempVar84->Range = 9;
            MagicInfoList.push_back(tempVar84);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar84' statement was not added since tempVar84 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ExplosiveTrap))
        {
            MagicInfo *tempVar85 = new MagicInfo();
            tempVar85->Name = "ExplosiveTrap";
            tempVar85->Spell = Spell::ExplosiveTrap;
            tempVar85->Icon = 91;
            tempVar85->Level1 = 22;
            tempVar85->Level2 = 25;
            tempVar85->Level3 = 30;
            tempVar85->Need1 = 2000;
            tempVar85->Need2 = 3500;
            tempVar85->Need3 = 5000;
            tempVar85->BaseCost = 10;
            tempVar85->LevelCost = 3;
            tempVar85->MPowerBase = 15;
            tempVar85->PowerBase = 15;
            tempVar85->Range = 0;
            MagicInfoList.push_back(tempVar85);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar85' statement was not added since tempVar85 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::DelayedExplosion))
        {
            MagicInfo *tempVar86 = new MagicInfo();
            tempVar86->Name = "DelayedExplosion";
            tempVar86->Spell = Spell::DelayedExplosion;
            tempVar86->Icon = 92;
            tempVar86->Level1 = 31;
            tempVar86->Level2 = 34;
            tempVar86->Level3 = 39;
            tempVar86->Need1 = 3000;
            tempVar86->Need2 = 7000;
            tempVar86->Need3 = 10000;
            tempVar86->BaseCost = 8;
            tempVar86->LevelCost = 2;
            tempVar86->MPowerBase = 30;
            tempVar86->PowerBase = 15;
            tempVar86->Range = 9;
            MagicInfoList.push_back(tempVar86);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar86' statement was not added since tempVar86 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Meditation))
        {
            MagicInfo *tempVar87 = new MagicInfo();
            tempVar87->Name = "Meditation";
            tempVar87->Spell = Spell::Meditation;
            tempVar87->Icon = 93;
            tempVar87->Level1 = 19;
            tempVar87->Level2 = 24;
            tempVar87->Level3 = 29;
            tempVar87->Need1 = 1800;
            tempVar87->Need2 = 2600;
            tempVar87->Need3 = 5600;
            tempVar87->BaseCost = 8;
            tempVar87->LevelCost = 2;
            tempVar87->Range = 0;
            MagicInfoList.push_back(tempVar87);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar87' statement was not added since tempVar87 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ElementalShot))
        {
            MagicInfo *tempVar88 = new MagicInfo();
            tempVar88->Name = "ElementalShot";
            tempVar88->Spell = Spell::ElementalShot;
            tempVar88->Icon = 94;
            tempVar88->Level1 = 20;
            tempVar88->Level2 = 25;
            tempVar88->Level3 = 31;
            tempVar88->Need1 = 1800;
            tempVar88->Need2 = 2700;
            tempVar88->Need3 = 6000;
            tempVar88->BaseCost = 8;
            tempVar88->LevelCost = 2;
            tempVar88->MPowerBase = 6;
            tempVar88->PowerBase = 3;
            tempVar88->Range = 9;
            MagicInfoList.push_back(tempVar88);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar88' statement was not added since tempVar88 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::Concentration))
        {
            MagicInfo *tempVar89 = new MagicInfo();
            tempVar89->Name = "Concentration";
            tempVar89->Spell = Spell::Concentration;
            tempVar89->Icon = 96;
            tempVar89->Level1 = 23;
            tempVar89->Level2 = 27;
            tempVar89->Level3 = 32;
            tempVar89->Need1 = 2100;
            tempVar89->Need2 = 3800;
            tempVar89->Need3 = 6500;
            tempVar89->BaseCost = 8;
            tempVar89->LevelCost = 2;
            tempVar89->Range = 0;
            MagicInfoList.push_back(tempVar89);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar89' statement was not added since tempVar89 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::ElementalBarrier))
        {
            MagicInfo *tempVar90 = new MagicInfo();
            tempVar90->Name = "ElementalBarrier";
            tempVar90->Spell = Spell::ElementalBarrier;
            tempVar90->Icon = 98;
            tempVar90->Level1 = 33;
            tempVar90->Level2 = 38;
            tempVar90->Level3 = 44;
            tempVar90->Need1 = 3000;
            tempVar90->Need2 = 7000;
            tempVar90->Need3 = 10000;
            tempVar90->BaseCost = 10;
            tempVar90->LevelCost = 2;
            tempVar90->MPowerBase = 15;
            tempVar90->PowerBase = 5;
            tempVar90->Range = 0;
            MagicInfoList.push_back(tempVar90);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar90' statement was not added since tempVar90 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::BackStep))
        {
            MagicInfo *tempVar91 = new MagicInfo();
            tempVar91->Name = "BackStep";
            tempVar91->Spell = Spell::BackStep;
            tempVar91->Icon = 95;
            tempVar91->Level1 = 30;
            tempVar91->Level2 = 34;
            tempVar91->Level3 = 38;
            tempVar91->Need1 = 2400;
            tempVar91->Need2 = 3000;
            tempVar91->Need3 = 6000;
            tempVar91->BaseCost = 12;
            tempVar91->LevelCost = 2;
            tempVar91->DelayBase = 2500;
            tempVar91->Range = 0;
            MagicInfoList.push_back(tempVar91);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar91' statement was not added since tempVar91 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::BindingShot))
        {
            MagicInfo *tempVar92 = new MagicInfo();
            tempVar92->Name = "BindingShot";
            tempVar92->Spell = Spell::BindingShot;
            tempVar92->Icon = 97;
            tempVar92->Level1 = 35;
            tempVar92->Level2 = 39;
            tempVar92->Level3 = 42;
            tempVar92->Need1 = 400;
            tempVar92->Need2 = 7000;
            tempVar92->Need3 = 9500;
            tempVar92->BaseCost = 7;
            tempVar92->LevelCost = 3;
            tempVar92->Range = 9;
            MagicInfoList.push_back(tempVar92);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar92' statement was not added since tempVar92 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonVampire))
        {
            MagicInfo *tempVar93 = new MagicInfo();
            tempVar93->Name = "SummonVampire";
            tempVar93->Spell = Spell::SummonVampire;
            tempVar93->Icon = 99;
            tempVar93->Level1 = 28;
            tempVar93->Level2 = 33;
            tempVar93->Level3 = 41;
            tempVar93->Need1 = 2000;
            tempVar93->Need2 = 2700;
            tempVar93->Need3 = 7500;
            tempVar93->BaseCost = 10;
            tempVar93->LevelCost = 5;
            tempVar93->Range = 9;
            MagicInfoList.push_back(tempVar93);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar93' statement was not added since tempVar93 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::VampireShot))
        {
            MagicInfo *tempVar94 = new MagicInfo();
            tempVar94->Name = "VampireShot";
            tempVar94->Spell = Spell::VampireShot;
            tempVar94->Icon = 100;
            tempVar94->Level1 = 26;
            tempVar94->Level2 = 32;
            tempVar94->Level3 = 36;
            tempVar94->Need1 = 3000;
            tempVar94->Need2 = 6000;
            tempVar94->Need3 = 12000;
            tempVar94->BaseCost = 12;
            tempVar94->LevelCost = 3;
            tempVar94->MPowerBase = 10;
            tempVar94->PowerBase = 7;
            tempVar94->Range = 9;
            MagicInfoList.push_back(tempVar94);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar94' statement was not added since tempVar94 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonToad))
        {
            MagicInfo *tempVar95 = new MagicInfo();
            tempVar95->Name = "SummonToad";
            tempVar95->Spell = Spell::SummonToad;
            tempVar95->Icon = 101;
            tempVar95->Level1 = 37;
            tempVar95->Level2 = 43;
            tempVar95->Level3 = 47;
            tempVar95->Need1 = 5800;
            tempVar95->Need2 = 10000;
            tempVar95->Need3 = 13000;
            tempVar95->BaseCost = 10;
            tempVar95->LevelCost = 5;
            tempVar95->Range = 9;
            MagicInfoList.push_back(tempVar95);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar95' statement was not added since tempVar95 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::PoisonShot))
        {
            MagicInfo *tempVar96 = new MagicInfo();
            tempVar96->Name = "PoisonShot";
            tempVar96->Spell = Spell::PoisonShot;
            tempVar96->Icon = 102;
            tempVar96->Level1 = 40;
            tempVar96->Level2 = 45;
            tempVar96->Level3 = 49;
            tempVar96->Need1 = 6000;
            tempVar96->Need2 = 14000;
            tempVar96->Need3 = 16000;
            tempVar96->BaseCost = 10;
            tempVar96->LevelCost = 4;
            tempVar96->MPowerBase = 10;
            tempVar96->PowerBase = 10;
            tempVar96->Range = 9;
            MagicInfoList.push_back(tempVar96);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar96' statement was not added since tempVar96 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::CrippleShot))
        {
            MagicInfo *tempVar97 = new MagicInfo();
            tempVar97->Name = "CrippleShot";
            tempVar97->Spell = Spell::CrippleShot;
            tempVar97->Icon = 103;
            tempVar97->Level1 = 43;
            tempVar97->Level2 = 47;
            tempVar97->Level3 = 50;
            tempVar97->Need1 = 12000;
            tempVar97->Need2 = 15000;
            tempVar97->Need3 = 18000;
            tempVar97->BaseCost = 15;
            tempVar97->LevelCost = 3;
            tempVar97->MPowerBase = 10;
            tempVar97->MPowerBonus = 20;
            tempVar97->PowerBase = 10;
            tempVar97->Range = 9;
            MagicInfoList.push_back(tempVar97);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar97' statement was not added since tempVar97 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::SummonSnakes))
        {
            MagicInfo *tempVar98 = new MagicInfo();
            tempVar98->Name = "SummonSnakes";
            tempVar98->Spell = Spell::SummonSnakes;
            tempVar98->Icon = 104;
            tempVar98->Level1 = 46;
            tempVar98->Level2 = 51;
            tempVar98->Level3 = 54;
            tempVar98->Need1 = 14000;
            tempVar98->Need2 = 17000;
            tempVar98->Need3 = 20000;
            tempVar98->BaseCost = 10;
            tempVar98->LevelCost = 5;
            tempVar98->Range = 9;
            MagicInfoList.push_back(tempVar98);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar98' statement was not added since tempVar98 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::NapalmShot))
        {
            MagicInfo *tempVar99 = new MagicInfo();
            tempVar99->Name = "NapalmShot";
            tempVar99->Spell = Spell::NapalmShot;
            tempVar99->Icon = 105;
            tempVar99->Level1 = 48;
            tempVar99->Level2 = 52;
            tempVar99->Level3 = 55;
            tempVar99->Need1 = 15000;
            tempVar99->Need2 = 18000;
            tempVar99->Need3 = 21000;
            tempVar99->BaseCost = 40;
            tempVar99->LevelCost = 10;
            tempVar99->MPowerBase = 25;
            tempVar99->MPowerBonus = 25;
            tempVar99->PowerBase = 25;
            tempVar99->Range = 9;
            MagicInfoList.push_back(tempVar99);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar99' statement was not added since tempVar99 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::OneWithNature))
        {
            MagicInfo *tempVar100 = new MagicInfo();
            tempVar100->Name = "OneWithNature";
            tempVar100->Spell = Spell::OneWithNature;
            tempVar100->Icon = 106;
            tempVar100->Level1 = 50;
            tempVar100->Level2 = 53;
            tempVar100->Level3 = 56;
            tempVar100->Need1 = 17000;
            tempVar100->Need2 = 19000;
            tempVar100->Need3 = 24000;
            tempVar100->BaseCost = 80;
            tempVar100->LevelCost = 15;
            tempVar100->MPowerBase = 75;
            tempVar100->MPowerBonus = 35;
            tempVar100->PowerBase = 30;
            tempVar100->PowerBonus = 20;
            tempVar100->Range = 9;
            MagicInfoList.push_back(tempVar100);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar100' statement was not added since tempVar100 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MentalState))
        {
            MagicInfo *tempVar101 = new MagicInfo();
            tempVar101->Name = "MentalState";
            tempVar101->Spell = Spell::MentalState;
            tempVar101->Icon = 81;
            tempVar101->Level1 = 11;
            tempVar101->Level2 = 15;
            tempVar101->Level3 = 22;
            tempVar101->Need1 = 500;
            tempVar101->Need2 = 900;
            tempVar101->Need3 = 1800;
            tempVar101->BaseCost = 1;
            tempVar101->LevelCost = 1;
            tempVar101->Range = 0;
            MagicInfoList.push_back(tempVar101);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar101' statement was not added since tempVar101 was passed to a method or constructor. Handle memory management manually.
        }

        //Custom
        if (!MagicExists(Spell::Portal))
        {
            MagicInfo *tempVar102 = new MagicInfo();
            tempVar102->Name = "Portal";
            tempVar102->Spell = Spell::Portal;
            tempVar102->Icon = 1;
            tempVar102->Level1 = 7;
            tempVar102->Level2 = 11;
            tempVar102->Level3 = 14;
            tempVar102->Need1 = 150;
            tempVar102->Need2 = 350;
            tempVar102->Need3 = 700;
            tempVar102->BaseCost = 3;
            tempVar102->LevelCost = 2;
            tempVar102->Range = 9;
            MagicInfoList.push_back(tempVar102);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar102' statement was not added since tempVar102 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::BattleCry))
        {
            MagicInfo *tempVar103 = new MagicInfo();
            tempVar103->Name = "BattleCry";
            tempVar103->Spell = Spell::BattleCry;
            tempVar103->Icon = 42;
            tempVar103->Level1 = 48;
            tempVar103->Level2 = 51;
            tempVar103->Level3 = 55;
            tempVar103->Need1 = 8000;
            tempVar103->Need2 = 11000;
            tempVar103->Need3 = 15000;
            tempVar103->BaseCost = 22;
            tempVar103->LevelCost = 10;
            tempVar103->Range = 0;
            MagicInfoList.push_back(tempVar103);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar103' statement was not added since tempVar103 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::FireBounce))
        {
            MagicInfo *tempVar104 = new MagicInfo();
            tempVar104->Name = "FireBounce";
            tempVar104->Spell = Spell::FireBounce;
            tempVar104->Icon = 4;
            tempVar104->Level1 = 15;
            tempVar104->Level2 = 18;
            tempVar104->Level3 = 21;
            tempVar104->Need1 = 2000;
            tempVar104->Need2 = 2700;
            tempVar104->Need3 = 3500;
            tempVar104->BaseCost = 5;
            tempVar104->LevelCost = 1;
            tempVar104->MPowerBase = 6;
            tempVar104->PowerBase = 10;
            tempVar104->Range = 9;
            MagicInfoList.push_back(tempVar104);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar104' statement was not added since tempVar104 was passed to a method or constructor. Handle memory management manually.
        }
        if (!MagicExists(Spell::MeteorShower))
        {
            MagicInfo *tempVar105 = new MagicInfo();
            tempVar105->Name = "MeteorShower";
            tempVar105->Spell = Spell::MeteorShower;
            tempVar105->Icon = 4;
            tempVar105->Level1 = 15;
            tempVar105->Level2 = 18;
            tempVar105->Level3 = 21;
            tempVar105->Need1 = 2000;
            tempVar105->Need2 = 2700;
            tempVar105->Need3 = 3500;
            tempVar105->BaseCost = 5;
            tempVar105->LevelCost = 1;
            tempVar105->MPowerBase = 6;
            tempVar105->PowerBase = 10;
            tempVar105->Range = 9;
            MagicInfoList.push_back(tempVar105);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar105' statement was not added since tempVar105 was passed to a method or constructor. Handle memory management manually.
        }
    }

    std::string Envir::CanStartEnvir()
    {
        if (Settings::EnforceDBChecks)
        {
            if (StartPoints.empty())
            {
                return "Cannot start server without start points";
            }

            if (GetMonsterInfo(Settings::SkeletonName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::SkeletonName;
            }
            if (GetMonsterInfo(Settings::ShinsuName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::ShinsuName;
            }
            if (GetMonsterInfo(Settings::BugBatName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BugBatName;
            }
            if (GetMonsterInfo(Settings::Zuma1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma1;
            }
            if (GetMonsterInfo(Settings::Zuma2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma2;
            }
            if (GetMonsterInfo(Settings::Zuma3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma3;
            }
            if (GetMonsterInfo(Settings::Zuma4, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma4;
            }
            if (GetMonsterInfo(Settings::Zuma5, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma5;
            }
            if (GetMonsterInfo(Settings::Zuma6, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma6;
            }
            if (GetMonsterInfo(Settings::Zuma7, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Zuma7;
            }
            if (GetMonsterInfo(Settings::Turtle1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Turtle1;
            }
            if (GetMonsterInfo(Settings::Turtle2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Turtle2;
            }
            if (GetMonsterInfo(Settings::Turtle3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Turtle3;
            }
            if (GetMonsterInfo(Settings::Turtle4, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Turtle4;
            }
            if (GetMonsterInfo(Settings::Turtle5, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::Turtle5;
            }
            if (GetMonsterInfo(Settings::BoneMonster1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BoneMonster1;
            }
            if (GetMonsterInfo(Settings::BoneMonster2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BoneMonster2;
            }
            if (GetMonsterInfo(Settings::BoneMonster3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BoneMonster3;
            }
            if (GetMonsterInfo(Settings::BoneMonster4, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BoneMonster4;
            }
            if (GetMonsterInfo(Settings::BehemothMonster1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BehemothMonster1;
            }
            if (GetMonsterInfo(Settings::BehemothMonster2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BehemothMonster2;
            }
            if (GetMonsterInfo(Settings::BehemothMonster3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BehemothMonster3;
            }
            if (GetMonsterInfo(Settings::HellKnight1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellKnight1;
            }
            if (GetMonsterInfo(Settings::HellKnight2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellKnight2;
            }
            if (GetMonsterInfo(Settings::HellKnight3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellKnight3;
            }
            if (GetMonsterInfo(Settings::HellKnight4, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellKnight4;
            }
            if (GetMonsterInfo(Settings::HellBomb1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellBomb1;
            }
            if (GetMonsterInfo(Settings::HellBomb2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellBomb2;
            }
            if (GetMonsterInfo(Settings::HellBomb3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::HellBomb3;
            }
            if (GetMonsterInfo(Settings::WhiteSnake, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::WhiteSnake;
            }
            if (GetMonsterInfo(Settings::AngelName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::AngelName;
            }
            if (GetMonsterInfo(Settings::BombSpiderName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::BombSpiderName;
            }
            if (GetMonsterInfo(Settings::CloneName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::CloneName;
            }
            if (GetMonsterInfo(Settings::AssassinCloneName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::AssassinCloneName;
            }
            if (GetMonsterInfo(Settings::VampireName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::VampireName;
            }
            if (GetMonsterInfo(Settings::ToadName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::ToadName;
            }
            if (GetMonsterInfo(Settings::SnakeTotemName, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::SnakeTotemName;
            }
            if (GetMonsterInfo(Settings::FishingMonster, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::FishingMonster;
            }
            if (GetMonsterInfo(Settings::GeneralMeowMeowMob1, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::GeneralMeowMeowMob1;
            }
            if (GetMonsterInfo(Settings::GeneralMeowMeowMob2, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::GeneralMeowMeowMob2;
            }
            if (GetMonsterInfo(Settings::GeneralMeowMeowMob3, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::GeneralMeowMeowMob3;
            }
            if (GetMonsterInfo(Settings::GeneralMeowMeowMob4, true) == nullptr)
            {
                return "Cannot start server without mob: " + Settings::GeneralMeowMeowMob4;
            }

            if (GetItemInfo(Settings::RefineOreName) == nullptr)
            {
                return "Cannot start server without item: " + Settings::RefineOreName;
            }
        }

        //add intelligent creature checks?

        return "true";
    }

    void Envir::WorkLoop()
    {
        try
        {
            setTime(Stopwatch->ElapsedMilliseconds);

            auto conTime = getTime();
            auto saveTime = getTime() + Settings::SaveDelay * Settings::Minute;
            auto userTime = getTime() + Settings::Minute * 5;
            auto lineMessageTime = getTime() + Settings::Minute * Settings::LineMessageTimer;
            auto processTime = getTime() + 1000;
            auto startTime = getTime();

            auto processCount = 0;
            auto processRealCount = 0;

            LinkedListNode<MapObject*> *current = nullptr;

            if (Settings::Multithreaded)
            {
                for (auto j = 0; j < MobThreads.size(); j++)
                {
                    MobThreads[j] = new MobThread();
                    MobThreads[j]->Id = j;
                }
            }

            StartEnvir();
            auto canstartserver = CanStartEnvir();
            if (canstartserver != "true")
            {
                getMessageQueue()->Enqueue(canstartserver);
                StopEnvir();
                _thread = nullptr;
                Stop();
                return;
            }

            if (Settings::Multithreaded)
            {
                for (auto j = 0; j < MobThreads.size(); j++)
                {
                    auto Info = MobThreads[j];
                    if (j <= 0)
                    {
                        continue;
                    }
                    Thread *tempVar = new Thread([&] ()
                    {
                        ThreadLoop(Info);
                    });
                    tempVar->IsBackground = true;
                    MobThreading[j] = tempVar;
                    MobThreading[j]->Start();

                    delete tempVar;
                }
            }

            StartNetwork();
            if (Settings::StartHTTPService)
            {
                http = new HttpServer();
                http->Start();
            }
            try
            {
                while (getRunning())
                {
                    setTime(Stopwatch->ElapsedMilliseconds);

                    if (getTime() >= processTime)
                    {
                        LastCount = processCount;
                        LastRealCount = processRealCount;
                        processCount = 0;
                        processRealCount = 0;
                        processTime = getTime() + 1000;
                    }

                    if (conTime != getTime())
                    {
                        conTime = getTime();

                        AdjustLights();

                        {
                            std::scoped_lock<std::mutex> lock(Connections);
                            for (auto i = Connections.size() - 1; i >= 0; i--)
                            {
                                Connections[i]->Process();
                            }
                        }

                        {
                            std::scoped_lock<std::mutex> lock(StatusConnections);
                            for (auto i = StatusConnections.size() - 1; i >= 0; i--)
                            {
                                StatusConnections[i]->Process();
                            }
                        }
                    }


                    if (current == nullptr)
                    {
                        current = Objects.First;
                    }

                    if (current == Objects.First)
                    {
                        LastRunTime = getTime() - startTime;
                        startTime = getTime();
                    }

                    if (Settings::Multithreaded)
                    {
                        for (auto j = 1; j < MobThreads.size(); j++)
                        {
                            auto Info = MobThreads[j];

                            if (!Info->Stop)
                            {
                                continue;
                            }
                            Info->EndTime = getTime() + 10;
                            Info->Stop = false;
                        }
                        {
                            std::scoped_lock<std::mutex> lock(_locker);
                            Monitor::PulseAll(_locker); //changing a blocking condition. (this makes the threads wake up!)
                        }
                        //run the first loop in the main thread so the main thread automaticaly 'halts' until the other threads are finished
                        ThreadLoop(MobThreads[0]);
                    }

                    auto TheEnd = false;
                    auto Start = Stopwatch->ElapsedMilliseconds;
                    while (!TheEnd && Stopwatch->ElapsedMilliseconds - Start < 20)
                    {
                        if (current == nullptr)
                        {
                            TheEnd = true;
                            break;
                        }

                        auto next = current->Next;
                        if (!Settings::Multithreaded || current->Value->getRace() != ObjectType::Monster || current->Value->Master != nullptr)
                        {
                            if (getTime() > current->Value->OperateTime)
                            {
                                current->Value->Process();
                                current->Value->SetOperateTime();
                            }
                            processCount++;
                        }
                        current = next;
                    }

                    for (auto i = 0; i < MapList.size(); i++)
                    {
                        MapList[i]->Process();
                    }

                    if (DragonSystem != nullptr)
                    {
                        DragonSystem->Process();
                    }

                    Process();

                    if (getTime() >= saveTime)
                    {
                        saveTime = getTime() + Settings::SaveDelay * Settings::Minute;
                        BeginSaveAccounts();
                        SaveGuilds();
                        SaveGoods();
                        SaveConquests();
                    }

                    if (getTime() >= userTime)
                    {
                        userTime = getTime() + Settings::Minute * 5;
                        S::Chat *tempVar2 = new S::Chat();
                        tempVar2->Message = std::string::Format(GameLanguage::OnlinePlayers, Players.size());
                        tempVar2->Type = ChatType::Hint;
                        Broadcast(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                    }

                    if (LineMessages.size() > 0 && getTime() >= lineMessageTime)
                    {
                        lineMessageTime = getTime() + Settings::Minute * Settings::LineMessageTimer;
                        S::Chat *tempVar3 = new S::Chat();
                        tempVar3->Message = LineMessages[Random->Next(LineMessages.size())];
                        tempVar3->Type = ChatType::LineMessage;
                        Broadcast(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
                    }

                    //   if (Players.Count == 0) Thread.Sleep(1);
                    //   GC.Collect();
                }
            }
            catch (const std::runtime_error &ex)
            {
                {
                    std::scoped_lock<std::mutex> lock(Connections);
                    for (auto i = Connections.size() - 1; i >= 0; i--)
                    {
                        Connections[i]->SendDisconnect(3);
                    }
                }

                // Get stack trace for the exception with source file information
                auto st = new StackTrace(ex, true);
                // Get the top stack frame
                auto frame = st->GetFrame(0);
                // Get the line number from the stack frame
                auto line = frame->GetFileLineNumber();

                getMessageQueue()->Enqueue(StringHelper::formatSimple("[inner workloop error. Line {0}]", line) + ex);

                delete st;
            }

            StopNetwork();
            StopEnvir();
            SaveAccounts();
            SaveGuilds(true);
            SaveConquests(true);

        }
        catch (const std::runtime_error &ex)
        {
            // Get stack trace for the exception with source file information
            auto st = new StackTrace(ex, true);
            // Get the top stack frame
            auto frame = st->GetFrame(0);
            // Get the line number from the stack frame
            auto line = frame->GetFileLineNumber();

            getMessageQueue()->Enqueue(StringHelper::formatSimple("[outer workloop error. Line {0}]", line) + ex);

            delete st;
        }

        _thread = nullptr;
    }

    void Envir::ThreadLoop(MobThread *Info)
    {
        Info->Stop = false;

        try
        {

            auto stopping = false;
            if (Info->_current == nullptr)
            {
                Info->_current = Info->ObjectsList.First;
            }
            stopping = Info->_current == nullptr;

            while (getRunning())
            {
                if (Info->_current == nullptr)
                {
                    Info->_current = Info->ObjectsList.First;
                }
                else
                {
                    auto next = Info->_current->Next;

                    //if we reach the end of our list > go back to the top (since we are running threaded, we dont want the system to sit there for xxms doing nothing)
                    if (Info->_current == Info->ObjectsList.Last)
                    {
                        next = Info->ObjectsList.First;
                        Info->LastRunTime = (Info->LastRunTime + (getTime() - Info->StartTime)) / 2;
                        //Info.LastRunTime = (Time - Info.StartTime) /*> 0 ? (Time - Info.StartTime) : Info.LastRunTime */;
                        Info->StartTime = getTime();
                    }
                    if (getTime() > Info->_current->Value->OperateTime)
                    {
                        if (Info->_current->Value->Master == nullptr) //since we are running multithreaded, dont allow pets to be processed (unless you constantly move pets into their map appropriate thead)
                        {
                            Info->_current->Value->Process();
                            Info->_current->Value->SetOperateTime();
                        }
                    }
                    Info->_current = next;
                }

                //if it's the main thread > make it loop till the subthreads are done, else make it stop after 'endtime'
                if (Info->Id == 0)
                {
                    stopping = true;
                    for (auto x = 1; x < MobThreads.size(); x++)
                    {
                        if (MobThreads[x]->Stop == false)
                        {
                            stopping = false;
                        }
                    }
                    if (!stopping)
                    {
                        continue;
                    }
                    Info->Stop = stopping;
                    return;
                }

                if (Stopwatch->ElapsedMilliseconds <= Info->EndTime || !getRunning())
                {
                    continue;
                }
                Info->Stop = true;
                {
                    std::scoped_lock<std::mutex> lock(_locker);
                    while (Info->Stop)
                    {
                        Monitor::Wait(_locker);
                    }
                }
            }
        }
        catch (const std::runtime_error &ex)
        {
            if (dynamic_cast<ThreadInterruptedException*>(ex) != nullptr)
            {
                return;
            }

            getMessageQueue()->Enqueue(std::string::Format("[threadloop error]") + ex);
        }
    }

    void Envir::AdjustLights()
    {
        auto oldLights = Lights;

        auto hours = getNow().Hour * 2 % 24;
        if (hours == 6 || hours == 7)
        {
            Lights = LightSetting::Dawn;
        }
        else if (hours >= 8 && hours <= 15)
        {
            Lights = LightSetting::Day;
        }
        else if (hours == 16 || hours == 17)
        {
            Lights = LightSetting::Evening;
        }
        else
        {
            Lights = LightSetting::Night;
        }

        if (oldLights == Lights)
        {
            return;
        }

        S::TimeOfDay *tempVar = new S::TimeOfDay();
        tempVar->Lights = Lights;
        Broadcast(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::Process()
    {
        if (getNow().Day != dailyTime)
        {
            dailyTime = getNow().Day;
            ProcessNewDay();
        }

        if (getTime() >= warTime)
        {
            warTime = getTime() + Settings::Minute;
            for (auto i = GuildsAtWar.size() - 1; i >= 0; i--)
            {
                GuildsAtWar[i]->TimeRemaining -= Settings::Minute;

                if (GuildsAtWar[i]->TimeRemaining >= 0)
                {
                    continue;
                }
                GuildsAtWar[i]->EndWar();
                GuildsAtWar.erase(GuildsAtWar.begin() + i);
            }
        }

        if (getTime() >= guildTime)
        {
            guildTime = getTime() + Settings::Minute;
            for (auto i = 0; i < GuildList.size(); i++)
            {
                GuildList[i]->Process();
            }
        }

        if (getTime() >= conquestTime)
        {
            conquestTime = getTime() + Settings::Second * 10;
            for (auto i = 0; i < Conquests.size(); i++)
            {
                Conquests[i]->Process();
            }
        }

        if (getTime() >= rentalItemsTime)
        {
            rentalItemsTime = getTime() + Settings::Minute * 5;
            ProcessRentedItems();
        }

        if (getTime() >= auctionTime)
        {
            auctionTime = getTime() + Settings::Minute * 10;
            ProcessAuction();
        }

        if (getTime() >= spawnTime)
        {
            spawnTime = getTime() + Settings::Second * 10;
            getMain()->RespawnTick->Process();
        }

        if (getTime() >= robotTime)
        {
            robotTime = getTime() + Settings::Minute;
            Robot::Process(RobotNPC);
        }
    }

    void Envir::ProcessAuction()
    {
        LinkedListNode<AuctionInfo*> *current = Auctions.First;

        while (current != nullptr)
        {
            AuctionInfo *info = current->Value;

            if (!info->Expired && !info->Sold && getNow() >= info->ConsignmentDate.AddDays(Globals::ConsignmentLength))
            {
                if (info->ItemType == MarketItemType::Auction && info->CurrentBid > info->Price)
                {
                    std::string message = std::string::Format("You won {0} for {1:#,##0} Gold.", info->Item->getFriendlyName(), info->CurrentBid);

                    info->Sold = true;
                    MailCharacter(info->CurrentBuyerInfo, info->Item, 0, 0, message);

                    MessageAccount(info->CurrentBuyerInfo->AccountInfo, std::string::Format("You bought {0} for {1:#,##0} Gold", info->Item->getFriendlyName(), info->CurrentBid), ChatType::Hint);
                    MessageAccount(info->SellerInfo->AccountInfo, std::string::Format("You sold {0} for {1:#,##0} Gold", info->Item->getFriendlyName(), info->CurrentBid), ChatType::Hint);
                }
                else
                {
                    info->Expired = true;
                }
            }

            current = current->Next;
        }
    }

    void Envir::Broadcast(Packet *p)
    {
        for (auto i = 0; i < Players.size(); i++)
        {
            Players[i]->Enqueue(p);
        }
    }

    void Envir::RequiresBaseStatUpdate()
    {
        for (auto i = 0; i < Players.size(); i++)
        {
            Players[i]->HasUpdatedBaseStats = false;
        }
    }

    void Envir::SaveDB()
    {
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.Create(DatabasePath))
        {
            auto stream = File::Create(DatabasePath);
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var writer = new BinaryWriter(stream))
            {
            auto writer = BinaryWriter(stream);
            writer.Write(Version);
            writer.Write(CustomVersion);
            writer.Write(MapIndex);
            writer.Write(ItemIndex);
            writer.Write(MonsterIndex);
            writer.Write(NPCIndex);
            writer.Write(QuestIndex);
            writer.Write(GameshopIndex);
            writer.Write(ConquestIndex);
            writer.Write(RespawnIndex);

            writer.Write(MapInfoList.size());
            for (auto i = 0; i < MapInfoList.size(); i++)
            {
                MapInfoList[i]->Save(writer);
            }

            writer.Write(ItemInfoList.size());
            for (auto i = 0; i < ItemInfoList.size(); i++)
            {
                ItemInfoList[i]->Save(writer);
            }

            writer.Write(MonsterInfoList.size());
            for (auto i = 0; i < MonsterInfoList.size(); i++)
            {
                MonsterInfoList[i]->Save(writer);
            }

            writer.Write(NPCInfoList.size());
            for (auto i = 0; i < NPCInfoList.size(); i++)
            {
                NPCInfoList[i]->Save(writer);
            }

            writer.Write(QuestInfoList.size());
            for (auto i = 0; i < QuestInfoList.size(); i++)
            {
                QuestInfoList[i]->Save(writer);
            }

            DragonInfo->Save(writer);
            writer.Write(MagicInfoList.size());
            for (auto i = 0; i < MagicInfoList.size(); i++)
            {
                MagicInfoList[i]->Save(writer);
            }

            writer.Write(GameShopList.size());
            for (auto i = 0; i < GameShopList.size(); i++)
            {
                GameShopList[i]->Save(writer);
            }

            writer.Write(ConquestInfos.size());
            for (auto i = 0; i < ConquestInfos.size(); i++)
            {
                ConquestInfos[i]->Save(writer);
            }

            RespawnTick->Save(writer);
            }
        }
    }

    void Envir::SaveAccounts()
    {
        while (Saving)
        {
            delay(1);
        }

        try
        {
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.Create(AccountPath + "n"))
            {
                auto stream = File::Create(AccountPath + "n");
                SaveAccounts(stream);
            }
            if (FileSystem::fileExists(AccountPath))
            {
                FileSystem::renamePath(AccountPath, AccountPath + "o");
            }
            FileSystem::renamePath(AccountPath + "n", AccountPath);
            if (FileSystem::fileExists(AccountPath + "o"))
            {
                File::Delete(AccountPath + "o");
            }
        }
        catch (const std::runtime_error &ex)
        {
            getMessageQueue()->Enqueue(ex);
        }
    }

    void Envir::SaveAccounts(Stream *stream)
    {
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var writer = new BinaryWriter(stream))
        {
            auto writer = BinaryWriter(stream);
            writer.Write(Version);
            writer.Write(CustomVersion);
            writer.Write(NextAccountID);
            writer.Write(NextCharacterID);
            writer.Write(NextUserItemID);
            writer.Write(GuildList.size());
            writer.Write(NextGuildID);
            writer.Write(AccountList.size());
            for (auto i = 0; i < AccountList.size(); i++)
            {
                AccountList[i]->Save(writer);
            }

            writer.Write(NextAuctionID);
            writer.Write(Auctions.size());
            for (auto auction : Auctions)
            {
                auction->Save(writer);
            }

            writer.Write(NextMailID);

            writer.Write(GameshopLog.size());
            for (auto item : GameshopLog)
            {
                writer.Write(item.Key);
                writer.Write(item.Value);
            }

            writer.Write(SavedSpawns.size());
            for (auto Spawn : SavedSpawns)
            {
                auto Save = new RespawnSave();
                Save->RespawnIndex = Spawn->Info->RespawnIndex;
                Save->NextSpawnTick = Spawn->NextSpawnTick;
                Save->Spawned = Spawn->Count >= Spawn->Info->Count * SpawnMultiplier;
                Save->Save(writer);

                delete Save;
            }
        }
    }

    void Envir::SaveGuilds(bool forced)
    {
        if (!FileSystem::directoryExists(Settings::GuildPath))
        {
            FileSystem::createDirectory(Settings::GuildPath);
        }
        for (auto i = 0; i < GuildList.size(); i++)
        {
            if (GuildList[i]->NeedSave || forced)
            {
                GuildList[i]->NeedSave = false;
                auto mStream = new MemoryStream();
                auto writer = new BinaryWriter(mStream);
                GuildList[i]->Save(writer);
                auto fStream = new FileStream(FileSystem::combine(Settings::GuildPath, std::to_string(i) + ".mgdn"), FileMode::Create);
                auto data = mStream->ToArray();
                fStream->BeginWrite(data, 0, data.size(), [&] (System::IAsyncResult ar) {EndSaveGuildsAsync(ar);}, fStream);

//C# TO C++ CONVERTER TODO TASK: A 'delete fStream' statement was not added since fStream was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete writer' statement was not added since writer was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete mStream' statement was not added since mStream was passed to a method or constructor. Handle memory management manually.
            }
        }
    }

    void Envir::EndSaveGuildsAsync(IAsyncResult *result)
    {
        auto fStream = dynamic_cast<FileStream*>(result->AsyncState);
        try
        {
            if (fStream == nullptr)
            {
                return;
            }
            auto oldfilename = fStream->Name.substr(0, fStream->Name.length() - 1);
            auto newfilename = fStream->Name;
            fStream->EndWrite(result);
            fStream->Dispose();
            if (FileSystem::fileExists(oldfilename))
            {
                FileSystem::renamePath(oldfilename, oldfilename + "o");
            }
            FileSystem::renamePath(newfilename, oldfilename);
            if (FileSystem::fileExists(oldfilename + "o"))
            {
                File::Delete(oldfilename + "o");
            }
        }
        catch (const std::runtime_error &e1)
        {
        }
    }

    void Envir::SaveGoods(bool forced)
    {
        if (!FileSystem::directoryExists(Settings::GoodsPath))
        {
            FileSystem::createDirectory(Settings::GoodsPath);
        }

        for (auto i = 0; i < MapList.size(); i++)
        {
            auto map = MapList[i];

            if (map->NPCs.empty())
            {
                continue;
            }

            for (auto j = 0; j < map->NPCs.size(); j++)
            {
                auto npc = map->NPCs[j];

                if (forced)
                {
                    npc->ProcessGoods(forced);
                }

                if (!npc->NeedSave)
                {
                    continue;
                }

                auto path = FileSystem::combine(Settings::GoodsPath, std::to_string(npc->Info->Index) + ".msdn");

                auto mStream = new MemoryStream();
                auto writer = new BinaryWriter(mStream);
                auto Temp = 9999;
                writer->Write(Temp);
                writer->Write(Version);
                writer->Write(CustomVersion);
                writer->Write(npc->UsedGoods.size());

                for (auto k = 0; k < npc->UsedGoods.size(); k++)
                {
                    npc->UsedGoods[k]->Save(writer);
                }

                auto fStream = new FileStream(path, FileMode::Create);
                auto data = mStream->ToArray();
                fStream->BeginWrite(data, 0, data.size(), [&] (System::IAsyncResult ar) {EndSaveGoodsAsync(ar);}, fStream);

//C# TO C++ CONVERTER TODO TASK: A 'delete fStream' statement was not added since fStream was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete writer' statement was not added since writer was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete mStream' statement was not added since mStream was passed to a method or constructor. Handle memory management manually.
            }
        }
    }

    void Envir::EndSaveGoodsAsync(IAsyncResult *result)
    {
        try
        {
            auto fStream = dynamic_cast<FileStream*>(result->AsyncState);
            if (fStream == nullptr)
            {
                return;
            }
            auto oldfilename = fStream->Name.substr(0, fStream->Name.length() - 1);
            auto newfilename = fStream->Name;
            fStream->EndWrite(result);
            fStream->Dispose();
            if (FileSystem::fileExists(oldfilename))
            {
                FileSystem::renamePath(oldfilename, oldfilename + "o");
            }
            FileSystem::renamePath(newfilename, oldfilename);
            if (FileSystem::fileExists(oldfilename + "o"))
            {
                File::Delete(oldfilename + "o");
            }
        }
        catch (const std::runtime_error &e1)
        {
        }
    }

    void Envir::SaveConquests(bool forced)
    {
        if (!FileSystem::directoryExists(Settings::ConquestsPath))
        {
            FileSystem::createDirectory(Settings::ConquestsPath);
        }
        for (auto i = 0; i < Conquests.size(); i++)
        {
            if (!Conquests[i]->NeedSave && !forced)
            {
                continue;
            }
            Conquests[i]->NeedSave = false;
            auto mStream = new MemoryStream();
            auto writer = new BinaryWriter(mStream);
            Conquests[i]->Save(writer);
            auto fStream = new FileStream(FileSystem::combine(Settings::ConquestsPath, std::to_string(Conquests[i]->Info.Index) + ".mcdn"), FileMode::Create);
            auto data = mStream->ToArray();
            fStream->BeginWrite(data, 0, data.size(), [&] (System::IAsyncResult ar) {EndSaveConquestsAsync(ar);}, fStream);

//C# TO C++ CONVERTER TODO TASK: A 'delete fStream' statement was not added since fStream was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete writer' statement was not added since writer was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete mStream' statement was not added since mStream was passed to a method or constructor. Handle memory management manually.
        }
    }

    void Envir::EndSaveConquestsAsync(IAsyncResult *result)
    {
        auto fStream = dynamic_cast<FileStream*>(result->AsyncState);
        try
        {
            if (fStream == nullptr)
            {
                return;
            }
            auto oldfilename = fStream->Name.substr(0, fStream->Name.length() - 1);
            auto newfilename = fStream->Name;
            fStream->EndWrite(result);
            fStream->Dispose();
            if (FileSystem::fileExists(oldfilename))
            {
                FileSystem::renamePath(oldfilename, oldfilename + "o");
            }
            FileSystem::renamePath(newfilename, oldfilename);
            if (FileSystem::fileExists(oldfilename + "o"))
            {
                File::Delete(oldfilename + "o");
            }
        }
        catch (const std::runtime_error &e1)
        {

        }
    }

    void Envir::BeginSaveAccounts()
    {
        if (Saving)
        {
            return;
        }

        Saving = true;


//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var mStream = new MemoryStream())
        {
            auto mStream = MemoryStream();
            if (FileSystem::fileExists(AccountPath))
            {
                if (!FileSystem::directoryExists(BackUpPath))
                {
                    FileSystem::createDirectory(BackUpPath);
                }
                auto fileName = std::string::Format("Accounts {0:0000}-{1:00}-{2:00} {3:00}-{4:00}-{5:00}.bak", getNow().Year, getNow().Month, getNow().Day, getNow().Hour, getNow().Minute, getNow().Second);
                if (FileSystem::fileExists(FileSystem::combine(BackUpPath, fileName)))
                {
                    File::Delete(FileSystem::combine(BackUpPath, fileName));
                }
                FileSystem::renamePath(AccountPath, FileSystem::combine(BackUpPath, fileName));
            }

            SaveAccounts(mStream);
            auto fStream = new FileStream(AccountPath + "n", FileMode::Create);

            auto data = mStream.ToArray();
            fStream->BeginWrite(data, 0, data.size(), [&] (System::IAsyncResult ar) {EndSaveAccounts(ar);}, fStream);

//C# TO C++ CONVERTER TODO TASK: A 'delete fStream' statement was not added since fStream was passed to a method or constructor. Handle memory management manually.
        }

    }

    void Envir::EndSaveAccounts(IAsyncResult *result)
    {
        auto fStream = dynamic_cast<FileStream*>(result->AsyncState);
        try
        {
            if (fStream != nullptr)
            {
                auto oldfilename = fStream->Name.substr(0, fStream->Name.length() - 1);
                auto newfilename = fStream->Name;
                fStream->EndWrite(result);
                fStream->Dispose();
                if (FileSystem::fileExists(oldfilename))
                {
                    FileSystem::renamePath(oldfilename, oldfilename + "o");
                }
                FileSystem::renamePath(newfilename, oldfilename);
                if (FileSystem::fileExists(oldfilename + "o"))
                {
                    File::Delete(oldfilename + "o");
                }
            }
        }
        catch (const std::runtime_error &e1)
        {
        }

        Saving = false;
    }

    bool Envir::LoadDB()
    {
        {
            std::scoped_lock<std::mutex> lock(LoadLock);
            if (!FileSystem::fileExists(DatabasePath))
            {
                SaveDB();
            }

//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.OpenRead(DatabasePath))
            {
                auto stream = File::OpenRead(DatabasePath);
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var reader = new BinaryReader(stream))
                {
                auto reader = BinaryReader(stream);
                LoadVersion = reader.ReadInt32();
                LoadCustomVersion = reader.ReadInt32();

                if (LoadVersion < MinVersion)
                {
                    getMessageQueue()->Enqueue(StringHelper::formatSimple("Cannot load a database version {0}. Mininum supported is {1}.", Envir::LoadVersion, Envir::MinVersion));
                    return false;
                }

                MapIndex = reader.ReadInt32();
                ItemIndex = reader.ReadInt32();
                MonsterIndex = reader.ReadInt32();

                NPCIndex = reader.ReadInt32();
                QuestIndex = reader.ReadInt32();

                if (LoadVersion >= 63)
                {
                    GameshopIndex = reader.ReadInt32();
                }

                if (LoadVersion >= 66)
                {
                    ConquestIndex = reader.ReadInt32();
                }

                if (LoadVersion >= 68)
                {
                    RespawnIndex = reader.ReadInt32();
                }


                auto count = reader.ReadInt32();
                MapInfoList.clear();
                for (auto i = 0; i < count; i++)
                {
                    MapInfo tempVar(reader);
                    MapInfoList.push_back(&tempVar);
                }

                count = reader.ReadInt32();
                ItemInfoList.clear();
                for (auto i = 0; i < count; i++)
                {
                    ItemInfo tempVar2(reader, LoadVersion, LoadCustomVersion);
                    ItemInfoList.push_back(&tempVar2);
                    if (ItemInfoList[i] != nullptr && ItemInfoList[i]->RandomStatsId < Settings::RandomItemStatsList.size())
                    {
                        ItemInfoList[i]->RandomStats = Settings::RandomItemStatsList[ItemInfoList[i]->RandomStatsId];
                    }
                }
                count = reader.ReadInt32();
                MonsterInfoList.clear();
                for (auto i = 0; i < count; i++)
                {
                    MonsterInfo tempVar3(reader);
                    MonsterInfoList.push_back(&tempVar3);
                }

                count = reader.ReadInt32();
                NPCInfoList.clear();
                for (auto i = 0; i < count; i++)
                {
                    NPCInfo tempVar4(reader);
                    NPCInfoList.push_back(&tempVar4);
                }

                count = reader.ReadInt32();
                QuestInfoList.clear();
                for (auto i = 0; i < count; i++)
                {
                    QuestInfo tempVar5(reader);
                    QuestInfoList.push_back(&tempVar5);
                }

                DragonInfo = new DragonInfo(reader);
                count = reader.ReadInt32();
                for (auto i = 0; i < count; i++)
                {
                    auto m = new MagicInfo(reader, LoadVersion, LoadCustomVersion);
                    if (!MagicExists(m->Spell))
                    {
                        MagicInfoList.push_back(m);
                    }

//C# TO C++ CONVERTER TODO TASK: A 'delete m' statement was not added since m was passed to a method or constructor. Handle memory management manually.
                }

                FillMagicInfoList();
                if (LoadVersion <= 70)
                {
                    UpdateMagicInfo();
                }

                if (LoadVersion >= 63)
                {
                    count = reader.ReadInt32();
                    GameShopList.clear();
                    for (auto i = 0; i < count; i++)
                    {
                        auto item = new GameShopItem(reader, LoadVersion, LoadCustomVersion);
                        if (getMain()->BindGameShop(item))
                        {
                            GameShopList.push_back(item);
                        }

//C# TO C++ CONVERTER TODO TASK: A 'delete item' statement was not added since item was passed to a method or constructor. Handle memory management manually.
                    }
                }

                if (LoadVersion >= 66)
                {
                    ConquestInfos.clear();
                    count = reader.ReadInt32();
                    for (auto i = 0; i < count; i++)
                    {
                        ConquestInfo tempVar6(reader);
                        ConquestInfos.push_back(&tempVar6);
                    }
                }

                if (LoadVersion > 67)
                {
                    RespawnTick = new RespawnTimer(reader);
                }

                }
            }

            Settings::LinkGuildCreationItems(ItemInfoList);
        }

        return true;
    }

    void Envir::LoadAccounts()
    {
        //reset ranking
        for (auto i = 0; i < RankClass.Count(); i++)
        {
            if (!RankClass[i].empty())
            {
                RankClass[i].clear();
            }
            else
            {
                RankClass[i] = std::vector<RankCharacterInfo*>();
            }
        }
        RankTop.clear();
        for (auto i = 0; i < RankBottomLevel.Count(); i++)
        {
            RankBottomLevel[i] = 0;
        }

        {
            std::scoped_lock<std::mutex> lock(LoadLock);
            if (!FileSystem::fileExists(AccountPath))
            {
                SaveAccounts();
            }

//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.OpenRead(AccountPath))
            {
                auto stream = File::OpenRead(AccountPath);
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var reader = new BinaryReader(stream))
                {
                auto reader = BinaryReader(stream);
                LoadVersion = reader.ReadInt32();
                LoadCustomVersion = reader.ReadInt32();
                NextAccountID = reader.ReadInt32();
                NextCharacterID = reader.ReadInt32();
                NextUserItemID = reader.ReadUInt64();

                GuildCount = reader.ReadInt32();
                NextGuildID = reader.ReadInt32();

                auto count = reader.ReadInt32();
                AccountList.clear();
                CharacterList.clear();
                for (auto i = 0; i < count; i++)
                {
                    AccountInfo tempVar(reader);
                    AccountList.push_back(&tempVar);
                    CharacterList.insert(CharacterList.end(), (AccountList[i]->Characters).begin(), (AccountList[i]->Characters).end());
                }

                for (auto auction : Auctions)
                {
                    auction->SellerInfo.AccountInfo.Auctions->Remove(auction);
                }
                Auctions.clear();

                NextAuctionID = reader.ReadUInt64();


                count = reader.ReadInt32();
                for (auto i = 0; i < count; i++)
                {
                    auto auction = new AuctionInfo(reader, LoadVersion, LoadCustomVersion);

                    if (!BindItem(auction->Item) || !BindCharacter(auction))
                    {
//C# TO C++ CONVERTER TODO TASK: A 'delete auction' statement was not added since auction was passed to a method or constructor. Handle memory management manually.
                        continue;
                    }

                    Auctions.push_back(auction);
                    auction->SellerInfo->AccountInfo->Auctions.push_back(auction);

//C# TO C++ CONVERTER TODO TASK: A 'delete auction' statement was not added since auction was passed to a method or constructor. Handle memory management manually.
                }

                NextMailID = reader.ReadUInt64();

                if (LoadVersion <= 80)
                {
                    count = reader.ReadInt32();
                    for (auto i = 0; i < count; i++)
                    {
                        auto mail = new MailInfo(reader, LoadVersion, LoadCustomVersion);

                        mail->RecipientInfo = GetCharacterInfo(mail->RecipientIndex);

                        if (mail->RecipientInfo != nullptr)
                        {
                            mail->RecipientInfo->Mail.push_back(mail); //add to players inbox
                        }

//C# TO C++ CONVERTER TODO TASK: A 'delete mail' statement was not added since mail was passed to a method or constructor. Handle memory management manually.
                    }
                }

                if (LoadVersion >= 63)
                {
                    auto logCount = reader.ReadInt32();
                    for (auto i = 0; i < logCount; i++)
                    {
                        GameshopLog.emplace(reader.ReadInt32(), reader.ReadInt32());
                    }

                    if (ResetGS)
                    {
                        ClearGameshopLog();
                    }
                }

                if (LoadVersion >= 68)
                {
                    auto saveCount = reader.ReadInt32();
                    for (auto i = 0; i < saveCount; i++)
                    {
                        auto Saved = new RespawnSave(reader);
                        for (auto Respawn : SavedSpawns)
                        {
                            if (Respawn->Info->RespawnIndex != Saved->RespawnIndex)
                            {
                                continue;
                            }

                            Respawn->NextSpawnTick = Saved->NextSpawnTick;

                            if (!Saved->Spawned || Respawn->Info->Count * SpawnMultiplier <= Respawn->Count)
                            {
                                continue;
                            }

                            auto mobcount = Respawn->Info->Count * SpawnMultiplier - Respawn->Count;
                            for (auto j = 0; j < mobcount; j++)
                            {
                                Respawn->Spawn();
                            }
                        }

                        delete Saved;
                    }
                }
                }
            }
        }
    }

    void Envir::LoadGuilds()
    {
        {
            std::scoped_lock<std::mutex> lock(LoadLock);
            auto count = 0;

            GuildList.clear();

            for (auto i = 0; i < GuildCount; i++)
            {
                GuildObject *newGuild;
                if (!FileSystem::fileExists(FileSystem::combine(Settings::GuildPath, std::to_string(i) + ".mgd")))
                {
                    continue;
                }
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.OpenRead(Path.Combine(Settings.GuildPath, i + ".mgd")))
                {
                    auto stream = File::OpenRead(FileSystem::combine(Settings::GuildPath, std::to_string(i) + ".mgd"));
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var reader = new BinaryReader(stream))
                    {
                    auto reader = BinaryReader(stream);
                    newGuild = new GuildObject(reader);
                    }
                }

                //if (!newGuild.Ranks.Any(a => (byte)a.Options == 255)) continue;
                //if (GuildList.Any(e => e.Name == newGuild.Name)) continue;
                GuildList.push_back(newGuild);

                count++;

//C# TO C++ CONVERTER TODO TASK: A 'delete newGuild' statement was not added since newGuild was passed to a method or constructor. Handle memory management manually.
            }

            if (count != GuildCount)
            {
                GuildCount = count;
            }
        }
    }

    void Envir::LoadFishingDrops()
    {
        FishingDrops.clear();

        for (unsigned char i = 0; i <= 19; i++)
        {
            auto path = FileSystem::combine(Settings::DropPath, Settings::FishingDropFilename + ".txt");

//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
            path = StringHelper::replace(path, "00", i.ToString("D2"));

            if (!FileSystem::fileExists(path) && i < 2)
            {
                auto newfile = File::Create(path);
                newfile->Close();
            }

            if (!FileSystem::fileExists(path))
            {
                continue;
            }

            auto lines = File::ReadAllLines(path);

            for (auto j = 0; j < lines.size(); j++)
            {
                if (StringHelper::startsWith(lines[j], ";") || StringHelper::isEmptyOrWhiteSpace(lines[j]))
                {
                    continue;
                }

                auto drop = DropInfo::FromLine(lines[j]);
                if (drop == nullptr)
                {
                    getMessageQueue()->Enqueue(StringHelper::formatSimple("Could not load fishing drop: {0}", lines[j]));
                    continue;
                }

                drop->Type = i;

                FishingDrops.push_back(drop);
            }

//C# TO C++ CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result:
//ORIGINAL LINE: FishingDrops.Sort((drop1, drop2) =>
            std::sort(FishingDrops.begin(), FishingDrops.end(), [&] (drop1, drop2)
            {
                if (drop1::Chance > 0 && drop2->Chance == 0)
                {
                    return 1;
                }
                if (drop1->Chance == 0 && drop2::Chance > 0)
                {
                    return -1;
                }
    
                return drop1::Item->Type->CompareTo(drop2::Item->Type);
            });
        }
    }

    void Envir::LoadAwakeningMaterials()
    {
        AwakeningDrops.clear();

        auto path = FileSystem::combine(Settings::DropPath, Settings::AwakeningDropFilename + ".txt");

        if (!FileSystem::fileExists(path))
        {
            auto newfile = File::Create(path);
            newfile->Close();

        }

        auto lines = File::ReadAllLines(path);

        for (auto i = 0; i < lines.size(); i++)
        {
            if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
            {
                continue;
            }

            auto drop = DropInfo::FromLine(lines[i]);
            if (drop == nullptr)
            {
                getMessageQueue()->Enqueue(StringHelper::formatSimple("Could not load Awakening drop: {0}", lines[i]));
                continue;
            }

            AwakeningDrops.push_back(drop);
        }

//C# TO C++ CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result:
//ORIGINAL LINE: AwakeningDrops.Sort((drop1, drop2) =>
        std::sort(AwakeningDrops.begin(), AwakeningDrops.end(), [&] (drop1, drop2)
        {
            if (drop1::Chance > 0 && drop2->Chance == 0)
            {
                return 1;
            }
            if (drop1->Chance == 0 && drop2::Chance > 0)
            {
                return -1;
            }
    
            return drop1::Item->Type->CompareTo(drop2::Item->Type);
        });
    }

    void Envir::LoadStrongBoxDrops()
    {
        StrongboxDrops.clear();

        auto path = FileSystem::combine(Settings::DropPath, Settings::StrongboxDropFilename + ".txt");

        if (!FileSystem::fileExists(path))
        {
            auto newfile = File::Create(path);
            newfile->Close();
        }

        auto lines = File::ReadAllLines(path);

        for (auto i = 0; i < lines.size(); i++)
        {
            if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
            {
                continue;
            }

            auto drop = DropInfo::FromLine(lines[i]);
            if (drop == nullptr)
            {
                getMessageQueue()->Enqueue(StringHelper::formatSimple("Could not load strongbox drop: {0}", lines[i]));
                continue;
            }

            StrongboxDrops.push_back(drop);
        }

//C# TO C++ CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result:
//ORIGINAL LINE: StrongboxDrops.Sort((drop1, drop2) =>
        std::sort(StrongboxDrops.begin(), StrongboxDrops.end(), [&] (drop1, drop2)
        {
            if (drop1::Chance > 0 && drop2->Chance == 0)
            {
                return 1;
            }
            if (drop1->Chance == 0 && drop2::Chance > 0)
            {
                return -1;
            }
    
            return drop1::Item->Type->CompareTo(drop2::Item->Type);
        });
    }

    void Envir::LoadBlackStoneDrops()
    {
        BlackstoneDrops.clear();

        auto path = FileSystem::combine(Settings::DropPath, Settings::BlackstoneDropFilename + ".txt");

        if (!FileSystem::fileExists(path))
        {
            auto newfile = File::Create(path);
            newfile->Close();

        }

        auto lines = File::ReadAllLines(path);

        for (auto i = 0; i < lines.size(); i++)
        {
            if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
            {
                continue;
            }

            auto drop = DropInfo::FromLine(lines[i]);
            if (drop == nullptr)
            {
                getMessageQueue()->Enqueue(StringHelper::formatSimple("Could not load blackstone drop: {0}", lines[i]));
                continue;
            }

            BlackstoneDrops.push_back(drop);
        }

//C# TO C++ CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result:
//ORIGINAL LINE: BlackstoneDrops.Sort((drop1, drop2) =>
        std::sort(BlackstoneDrops.begin(), BlackstoneDrops.end(), [&] (drop1, drop2)
        {
            if (drop1::Chance > 0 && drop2->Chance == 0)
            {
                return 1;
            }
            if (drop1->Chance == 0 && drop2::Chance > 0)
            {
                return -1;
            }
    
            return drop1::Item->Type->CompareTo(drop2::Item->Type);
        });
    }

    void Envir::LoadConquests()
    {
        {
            std::scoped_lock<std::mutex> lock(LoadLock);
            auto count = 0;

            Conquests.clear();

            Map *tempMap;
            ConquestArcherObject *tempArcher;
            ConquestGateObject *tempGate;
            ConquestWallObject *tempWall;
            ConquestSiegeObject *tempSiege;

            for (auto i = 0; i < ConquestInfos.size(); i++)
            {
                ConquestObject *newConquest;
                tempMap = GetMap(ConquestInfos[i]->MapIndex);

                if (tempMap == nullptr)
                {
                    continue;
                }

                if (FileSystem::fileExists(FileSystem::combine(Settings::ConquestsPath, std::to_string(ConquestInfos[i]->Index) + ".mcd")))
                {
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var stream = File.OpenRead(Path.Combine(Settings.ConquestsPath, ConquestInfos[i].Index + ".mcd")))
                    {
                        auto stream = File::OpenRead(FileSystem::combine(Settings::ConquestsPath, std::to_string(ConquestInfos[i]->Index) + ".mcd"));
//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent:
//ORIGINAL LINE: using (var reader = new BinaryReader(stream))
                        {
                        auto reader = BinaryReader(stream);
                        newConquest = new ConquestObject(reader);
                        newConquest->Info = ConquestInfos[i];
                        newConquest->ConquestMap = tempMap;
                        }
                    }

                    for (auto k = 0; k < GuildList.size(); k++)
                    {
                        if (newConquest->Owner != GuildList[k]->Guildindex)
                        {
                            continue;
                        }
                        newConquest->Guild = GuildList[k];
                        GuildList[k]->Conquest = newConquest;
                    }

                    Conquests.push_back(newConquest);
                    tempMap->Conquest.push_back(newConquest);
                    count++;
                }
                else
                {
                    newConquest = new ConquestObject();
                    newConquest->Info = ConquestInfos[i];
                    newConquest->NeedSave = true;
                    newConquest->ConquestMap = tempMap;

                    Conquests.push_back(newConquest);
                    tempMap->Conquest.push_back(newConquest);
                }

                //Bind Info to Saved Archer objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ConquestGuards.size(); j++)
                {
                    tempArcher = newConquest->ArcherList.FirstOrDefault([&] (std::any x)
                    {
                        return x->Index == ConquestInfos[i]->ConquestGuards[j].Index;
                    });

                    if (tempArcher != nullptr)
                    {
                        tempArcher->Info = ConquestInfos[i]->ConquestGuards[j];
                        tempArcher->Conquest = newConquest;
                    }
                    else
                    {
                        ConquestArcherObject *tempVar = new ConquestArcherObject();
                        tempVar->Info = ConquestInfos[i]->ConquestGuards[j];
                        tempVar->Alive = true;
                        tempVar->Index = ConquestInfos[i]->ConquestGuards[j].Index;
                        tempVar->Conquest = newConquest;
                        newConquest->ArcherList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                    }
                }

                //Remove archers that have been removed from DB
                for (auto j = 0; j < newConquest->ArcherList.size(); j++)
                {
                    if (newConquest->ArcherList[j]->Info == nullptr)
                    {
                        newConquest->ArcherList.Remove(newConquest->ArcherList[j]);
                    }
                }

                //Bind Info to Saved Gate objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ConquestGates.size(); j++)
                {
                    tempGate = newConquest->GateList.FirstOrDefault([&] (std::any x)
                    {
                        return x->Index == ConquestInfos[i]->ConquestGates[j].Index;
                    });

                    if (tempGate != nullptr)
                    {
                        tempGate->Info = ConquestInfos[i]->ConquestGates[j];
                        tempGate->Conquest = newConquest;
                    }
                    else
                    {
                        ConquestGateObject *tempVar2 = new ConquestGateObject();
                        tempVar2->Info = ConquestInfos[i]->ConquestGates[j];
                        tempVar2->Health = std::numeric_limits<int>::max();
                        tempVar2->Index = ConquestInfos[i]->ConquestGates[j].Index;
                        tempVar2->Conquest = newConquest;
                        newConquest->GateList.push_back(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                    }
                }

                //Bind Info to Saved Flag objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ConquestFlags.size(); j++)
                {
                    ConquestFlagObject *tempVar3 = new ConquestFlagObject();
                    tempVar3->Info = ConquestInfos[i]->ConquestFlags[j];
                    tempVar3->Index = ConquestInfos[i]->ConquestFlags[j].Index;
                    tempVar3->Conquest = newConquest;
                    newConquest->FlagList.push_back(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
                }

                //Remove Gates that have been removed from DB
                for (auto j = 0; j < newConquest->GateList.size(); j++)
                {
                    if (newConquest->GateList[j]->Info == nullptr)
                    {
                        newConquest->GateList.Remove(newConquest->GateList[j]);
                    }
                }

                //Bind Info to Saved Wall objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ConquestWalls.size(); j++)
                {
                    tempWall = newConquest->WallList.FirstOrDefault([&] (std::any x)
                    {
                        return x->Index == ConquestInfos[i]->ConquestWalls[j].Index;
                    });

                    if (tempWall != nullptr)
                    {
                        tempWall->Info = ConquestInfos[i]->ConquestWalls[j];
                        tempWall->Conquest = newConquest;
                    }
                    else
                    {
                        ConquestWallObject *tempVar4 = new ConquestWallObject();
                        tempVar4->Info = ConquestInfos[i]->ConquestWalls[j];
                        tempVar4->Index = ConquestInfos[i]->ConquestWalls[j].Index;
                        tempVar4->Health = std::numeric_limits<int>::max();
                        tempVar4->Conquest = newConquest;
                        newConquest->WallList.push_back(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
                    }
                }

                //Remove Walls that have been removed from DB
                for (auto j = 0; j < newConquest->WallList.size(); j++)
                {
                    if (newConquest->WallList[j]->Info == nullptr)
                    {
                        newConquest->WallList.Remove(newConquest->WallList[j]);
                    }
                }


                //Bind Info to Saved Siege objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ConquestSieges.size(); j++)
                {
                    tempSiege = newConquest->SiegeList.FirstOrDefault([&] (std::any x)
                    {
                        return x->Index == ConquestInfos[i]->ConquestSieges[j].Index;
                    });

                    if (tempSiege != nullptr)
                    {
                        tempSiege->Info = ConquestInfos[i]->ConquestSieges[j];
                        tempSiege->Conquest = newConquest;
                    }
                    else
                    {
                        ConquestSiegeObject *tempVar5 = new ConquestSiegeObject();
                        tempVar5->Info = ConquestInfos[i]->ConquestSieges[j];
                        tempVar5->Index = ConquestInfos[i]->ConquestSieges[j].Index;
                        tempVar5->Health = std::numeric_limits<int>::max();
                        tempVar5->Conquest = newConquest;
                        newConquest->SiegeList.push_back(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                    }
                }

                //Remove Siege that have been removed from DB
                for (auto j = 0; j < newConquest->SiegeList.size(); j++)
                {
                    if (newConquest->SiegeList[j]->Info == nullptr)
                    {
                        newConquest->SiegeList.Remove(newConquest->SiegeList[j]);
                    }
                }

                //Bind Info to Saved Flag objects or create new objects
                for (auto j = 0; j < ConquestInfos[i]->ControlPoints.size(); j++)
                {
                    ConquestFlagObject *cp;
                    ConquestFlagObject *tempVar6 = new ConquestFlagObject(), *new;
                    tempVar6->Info = ConquestInfos[i]->ControlPoints[j];
                    tempVar6->Index = ConquestInfos[i]->ControlPoints[j].Index;
                    tempVar6->Conquest = newConquest;
                    newConquest->ControlPoints.emplace(cp = tempVar6, std::unordered_map<GuildObject*, int>());

                    cp->Spawn();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
                }


                newConquest->LoadArchers();
                newConquest->LoadGates();
                newConquest->LoadWalls();
                newConquest->LoadSieges();
                newConquest->LoadFlags();
                newConquest->LoadNPCs();

//C# TO C++ CONVERTER TODO TASK: A 'delete newConquest' statement was not added since newConquest was passed to a method or constructor. Handle memory management manually.
            }

//C# TO C++ CONVERTER TODO TASK: A 'delete tempSiege' statement was not added since tempSiege was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempWall' statement was not added since tempWall was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempGate' statement was not added since tempGate was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempArcher' statement was not added since tempArcher was passed to a method or constructor. Handle memory management manually.
        }
    }

    void Envir::LoadDisabledChars()
    {
        DisabledCharNames.clear();

        auto path = FileSystem::combine(Settings::EnvirPath, "DisabledChars.txt");

        if (!FileSystem::fileExists(path))
        {
            File::WriteAllText(path, "");
        }
        else
        {
            auto lines = File::ReadAllLines(path);

            for (auto i = 0; i < lines.size(); i++)
            {
                if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
                {
                    continue;
                }
                DisabledCharNames.push_back(StringHelper::toUpper(lines[i]));
            }
        }
    }

    void Envir::LoadLineMessages()
    {
        LineMessages.clear();

        auto path = FileSystem::combine(Settings::EnvirPath, "LineMessage.txt");

        if (!FileSystem::fileExists(path))
        {
            File::WriteAllText(path, "");
        }
        else
        {
            auto lines = File::ReadAllLines(path);

            for (auto i = 0; i < lines.size(); i++)
            {
                if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
                {
                    continue;
                }
                LineMessages.push_back(lines[i]);
            }
        }
    }

    bool Envir::BindCharacter(AuctionInfo *auction)
    {
        bool bound = false;

        for (int i = 0; i < CharacterList.size(); i++)
        {
            if (CharacterList[i]->Index == auction->SellerIndex)
            {
                auction->SellerInfo = CharacterList[i];
                bound = true;
            }

            else if (CharacterList[i]->Index == auction->CurrentBuyerIndex)
            {
                auction->CurrentBuyerInfo = CharacterList[i];
                bound = true;
            }
        }

        return bound;
    }

    void Envir::Start()
    {
        if (getRunning() || _thread != nullptr)
        {
            return;
        }

        setRunning(true);

        _thread = new Thread([&] () {WorkLoop();});
        _thread->IsBackground = true;
        _thread->Start();

    }

    void Envir::Stop()
    {
        setRunning(false);

        {
            std::scoped_lock<std::mutex> lock(_locker);
            Monitor::PulseAll(_locker); // changing a blocking condition. (this makes the threads wake up!)
        }

        //simply intterupt all the mob threads if they are running (will give an invisible error on them but fastest way of getting rid of them on shutdowns)
        for (auto i = 1; i < MobThreading.size(); i++)
        {
            if (MobThreads[i] != nullptr)
            {
                MobThreads[i]->EndTime = getTime() + 9999;
            }
            if (MobThreading[i] != nullptr && MobThreading[i]->ThreadState != System::Threading::ThreadState::Stopped && MobThreading[i]->ThreadState != System::Threading::ThreadState::Unstarted)
            {
                MobThreading[i]->Interrupt();
            }
        }

        if (http != nullptr)
        {
            http->Stop();
        }

        while (_thread != nullptr)
        {
                delay(1);
        }
    }

    void Envir::Reboot()
    {
        Thread tempVar([&] ()
        {
            getMessageQueue()->Enqueue("Server rebooting...");
            Stop();
            Start();
        });
        (&tempVar)->Start();
    }

    void Envir::StartEnvir()
    {
        Players.clear();
        StartPoints.clear();
        StartItems.clear();
        MapList.clear();
        GameshopLog.clear();
        CustomCommands.clear();
        MonsterCount = 0;

        LoadDB();

        RecipeInfoList.clear();
        for (auto recipe : Directory::GetFiles(Settings::RecipePath, "*.txt").Select([&] (std::any path)
        {
            return Path::GetFileNameWithoutExtension(path);
        })->ToArray())
        {
            RecipeInfo tempVar(recipe);
            RecipeInfoList.push_back(&tempVar);
        }

        getMessageQueue()->Enqueue(StringHelper::formatSimple("{0} Recipes Loaded.", RecipeInfoList.size()));

        for (auto i = 0; i < MapInfoList.size(); i++)
        {
            MapInfoList[i]->CreateMap();
        }
        getMessageQueue()->Enqueue(StringHelper::formatSimple("{0} Maps Loaded.", MapInfoList.size()));

        for (auto i = 0; i < ItemInfoList.size(); i++)
        {
            if (ItemInfoList[i]->StartItem)
            {
                StartItems.push_back(ItemInfoList[i]);
            }
        }

        for (auto i = 0; i < MonsterInfoList.size(); i++)
        {
            MonsterInfoList[i]->LoadDrops();
        }

        LoadFishingDrops();
        LoadAwakeningMaterials();
        LoadStrongBoxDrops();
        LoadBlackStoneDrops();
        getMessageQueue()->Enqueue("Drops Loaded.");

        LoadDisabledChars();
        LoadLineMessages();

        if (DragonInfo->Enabled)
        {
            DragonSystem = new Dragon(DragonInfo);
            if (DragonSystem != nullptr)
            {
                if (DragonSystem->Load())
                {
                    DragonSystem->Info->LoadDrops();
                }
            }

            getMessageQueue()->Enqueue("Dragon Loaded.");
        }

        DefaultNPC = NPCScript::GetOrAdd(static_cast<unsigned int>(Random->Next(1000000, 1999999)), Settings::DefaultNPCFilename, NPCScriptType::AutoPlayer);
        MonsterNPC = NPCScript::GetOrAdd(static_cast<unsigned int>(Random->Next(2000000, 2999999)), Settings::MonsterNPCFilename, NPCScriptType::AutoMonster);
        RobotNPC = NPCScript::GetOrAdd(static_cast<unsigned int>(Random->Next(3000000, 3999999)), Settings::RobotNPCFilename, NPCScriptType::Robot);

        getMessageQueue()->Enqueue("Envir Started.");
    }

    void Envir::StartNetwork()
    {
        Connections.clear();

        LoadAccounts();

        LoadGuilds();

        LoadConquests();

        _listener = new TcpListener(IPAddress::Parse(Settings::IPAddress), Settings::Port);
        _listener->Start();
        _listener->BeginAcceptTcpClient([&] (System::IAsyncResult ar) {Connection(ar);}, std::any());

        if (StatusPortEnabled)
        {
            _StatusPort = new TcpListener(IPAddress::Parse(Settings::IPAddress), 3000);
            _StatusPort->Start();
            _StatusPort->BeginAcceptTcpClient([&] (System::IAsyncResult ar) {StatusConnection(ar);}, std::any());
        }

        getMessageQueue()->Enqueue("Network Started.");
    }

    void Envir::StopEnvir()
    {
        SaveGoods(true);

        MapList.clear();
        StartPoints.clear();
        StartItems.clear();
        Objects.clear();
        Players.clear();

        CleanUp();

        GC::Collect();

        getMessageQueue()->Enqueue("Envir Stopped.");
    }

    void Envir::StopNetwork()
    {
        _listener->Stop();
        {
            std::scoped_lock<std::mutex> lock(Connections);
            for (auto i = Connections.size() - 1; i >= 0; i--)
            {
                Connections[i]->SendDisconnect(0);
            }
        }

        if (StatusPortEnabled)
        {
            _StatusPort->Stop();
            for (auto i = StatusConnections.size() - 1; i >= 0; i--)
            {
                StatusConnections[i]->SendDisconnect();
            }
        }

        auto expire = getTime() + 5000;

        while (Connections.size() != 0 && Stopwatch->ElapsedMilliseconds < expire)
        {
            setTime(Stopwatch->ElapsedMilliseconds);

            for (auto i = Connections.size() - 1; i >= 0; i--)
            {
                Connections[i]->Process();
            }

            delay(1);
        }


        Connections.clear();

        expire = getTime() + 10000;
        while (StatusConnections.size() != 0 && Stopwatch->ElapsedMilliseconds < expire)
        {
            setTime(Stopwatch->ElapsedMilliseconds);

            for (auto i = StatusConnections.size() - 1; i >= 0; i--)
            {
                StatusConnections[i]->Process();
            }

            delay(1);
        }


        StatusConnections.clear();
        getMessageQueue()->Enqueue("Network Stopped.");
    }

    void Envir::CleanUp()
    {
        for (auto i = 0; i < CharacterList.size(); i++)
        {
            auto info = CharacterList[i];

            if (info->Deleted)
            {
                #pragma region Mentor Cleanup
                if (info->Mentor > 0)
                {
                    auto Mentor = GetCharacterInfo(info->Mentor);

                    if (Mentor != nullptr)
                    {
                        Mentor->Mentor = 0;
                        Mentor->MentorExp = 0;
                        Mentor->isMentor = false;
                    }

                    info->Mentor = 0;
                    info->MentorExp = 0;
                    info->isMentor = false;
                }
                #pragma endregion

                #pragma region Marriage Cleanup
                if (info->Married > 0)
                {
                    auto Lover = GetCharacterInfo(info->Married);

                    info->Married = 0;
                    info->MarriedDate = DateTime::Now;

                    Lover->Married = 0;
                    Lover->MarriedDate = DateTime::Now;
                    if (Lover->Equipment[static_cast<int>(EquipmentSlot::RingL)] != nullptr)
                    {
                        Lover->Equipment[static_cast<int>(EquipmentSlot::RingL)]->WeddingRing = -1;
                    }
                }
                #pragma endregion

                if (info->DeleteDate < DateTime::Now.AddDays(-7))
                {
                    //delete char from db
                }
            }

            if (info->Mail.size() > Settings::MailCapacity)
            {
                for (auto j = info->Mail.size() - 1 - static_cast<int>(Settings::MailCapacity); j >= 0; j--)
                {
                    if (info->Mail[j]->DateOpened > DateTime::Now && info->Mail[j]->Collected && info->Mail[j]->Items->empty() && info->Mail[j]->Gold == 0)
                    {
                        info->Mail.Remove(info->Mail[j]);
                    }
                }
            }
        }
    }

    void Envir::Connection(IAsyncResult *result)
    {
        try
        {
            if (!getRunning() || !_listener->Server->IsBound)
            {
                return;
            }
        }
        catch (const std::runtime_error &e)
        {
            getMessageQueue()->Enqueue(e.what());
        }

        try
        {
            auto tempTcpClient = _listener->EndAcceptTcpClient(result);
            {
                std::scoped_lock<std::mutex> lock(Connections);
                MirConnection tempVar(++_sessionID, tempTcpClient);
                Connections.push_back(&tempVar);
            }
        }
        catch (const std::runtime_error &ex)
        {
            getMessageQueue()->Enqueue(ex);
        }
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to the exception 'finally' clause:
        finally
        {
            while (Connections.size() >= Settings::MaxUser)
            {
                delay(1);
            }

            if (getRunning() && _listener->Server->IsBound)
            {
                _listener->BeginAcceptTcpClient([&] (System::IAsyncResult ar) {Connection(ar);}, std::any());
            }
        }
    }

    void Envir::StatusConnection(IAsyncResult *result)
    {
        if (!getRunning() || !_StatusPort->Server->IsBound)
        {
            return;
        }

        try
        {
            auto tempTcpClient = _StatusPort->EndAcceptTcpClient(result);
            {
                std::scoped_lock<std::mutex> lock(StatusConnections);
                MirStatusConnection tempVar(tempTcpClient);
                StatusConnections.push_back(&tempVar);
            }
        }
        catch (const std::runtime_error &ex)
        {
            getMessageQueue()->Enqueue(ex);
        }
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to the exception 'finally' clause:
        finally
        {
            while (StatusConnections.size() >= 5) //dont allow to many status port connections it's just an abuse thing
            {
                delay(1);
            }

            if (getRunning() && _StatusPort->Server->IsBound)
            {
                _StatusPort->BeginAcceptTcpClient([&] (System::IAsyncResult ar) {StatusConnection(ar);}, std::any());
            }
        }
    }

    void Envir::NewAccount(ClientPackets::NewAccount *p, MirConnection *c)
    {
        if (!Settings::AllowNewAccount)
        {
            S::NewAccount *tempVar = new S::NewAccount();
            tempVar->Result = 0;
            c->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!AccountIDReg->IsMatch(p->AccountID))
        {
            S::NewAccount *tempVar2 = new S::NewAccount();
            tempVar2->Result = 1;
            c->Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!PasswordReg->IsMatch(p->Password))
        {
            S::NewAccount *tempVar3 = new S::NewAccount();
            tempVar3->Result = 2;
            c->Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            return;
        }
        if (!StringHelper::isEmptyOrWhiteSpace(p->EMailAddress) && !EMailReg->IsMatch(p->EMailAddress) || p->EMailAddress.length() > 50)
        {
            S::NewAccount *tempVar4 = new S::NewAccount();
            tempVar4->Result = 3;
            c->Enqueue(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->UserName) && p->UserName.length() > 20)
        {
            S::NewAccount *tempVar5 = new S::NewAccount();
            tempVar5->Result = 4;
            c->Enqueue(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->SecretQuestion) && p->SecretQuestion.length() > 30)
        {
            S::NewAccount *tempVar6 = new S::NewAccount();
            tempVar6->Result = 5;
            c->Enqueue(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->SecretAnswer) && p->SecretAnswer.length() > 30)
        {
            S::NewAccount *tempVar7 = new S::NewAccount();
            tempVar7->Result = 6;
            c->Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        {
            std::scoped_lock<std::mutex> lock(AccountLock);
            if (AccountExists(p->AccountID))
            {
                S::NewAccount *tempVar8 = new S::NewAccount();
                tempVar8->Result = 7;
                c->Enqueue(tempVar8);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
                return;
            }

            AccountInfo *tempVar9 = new AccountInfo(p);
            tempVar9->Index = ++NextAccountID;
            tempVar9->CreationIP = c->IPAddress;
            AccountList.push_back(tempVar9);


            S::NewAccount *tempVar10 = new S::NewAccount();
            tempVar10->Result = 8;
            c->Enqueue(tempVar10);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar10' statement was not added since tempVar10 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
        }
    }

    int Envir::HTTPNewAccount(ClientPackets::NewAccount *p, const std::string &ip)
    {
        if (!Settings::AllowNewAccount)
        {
            return 0;
        }

        if (!AccountIDReg->IsMatch(p->AccountID))
        {
            return 1;
        }

        if (!PasswordReg->IsMatch(p->Password))
        {
            return 2;
        }
        if (!StringHelper::isEmptyOrWhiteSpace(p->EMailAddress) && !EMailReg->IsMatch(p->EMailAddress) || p->EMailAddress.length() > 50)
        {
            return 3;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->UserName) && p->UserName.length() > 20)
        {
            return 4;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->SecretQuestion) && p->SecretQuestion.length() > 30)
        {
            return 5;
        }

        if (!StringHelper::isEmptyOrWhiteSpace(p->SecretAnswer) && p->SecretAnswer.length() > 30)
        {
            return 6;
        }

        {
            std::scoped_lock<std::mutex> lock(AccountLock);
            if (AccountExists(p->AccountID))
            {
                return 7;
            }

            AccountInfo *tempVar = new AccountInfo(p);
            tempVar->Index = ++NextAccountID;
            tempVar->CreationIP = ip;
            AccountList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return 8;
        }
    }

    void Envir::ChangePassword(ClientPackets::ChangePassword *p, MirConnection *c)
    {
        if (!Settings::AllowChangePassword)
        {
            S::ChangePassword *tempVar = new S::ChangePassword();
            tempVar->Result = 0;
            c->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!AccountIDReg->IsMatch(p->AccountID))
        {
            S::ChangePassword *tempVar2 = new S::ChangePassword();
            tempVar2->Result = 1;
            c->Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!PasswordReg->IsMatch(p->CurrentPassword))
        {
            S::ChangePassword *tempVar3 = new S::ChangePassword();
            tempVar3->Result = 2;
            c->Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!PasswordReg->IsMatch(p->NewPassword))
        {
            S::ChangePassword *tempVar4 = new S::ChangePassword();
            tempVar4->Result = 3;
            c->Enqueue(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        auto account = GetAccount(p->AccountID);

        if (account == nullptr)
        {
            S::ChangePassword *tempVar5 = new S::ChangePassword();
            tempVar5->Result = 4;
            c->Enqueue(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (account->Banned)
        {
            if (account->ExpiryDate > getNow())
            {
                S::ChangePasswordBanned *tempVar6 = new S::ChangePasswordBanned();
                tempVar6->Reason = account->BanReason;
                tempVar6->ExpiryDate = account->ExpiryDate;
                c->Enqueue(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
                return;
            }
            account->Banned = false;
        }
        account->BanReason = "";
        account->ExpiryDate = DateTime::MinValue;

        if (account->Password.compare(p->CurrentPassword) != 0)
        {
            S::ChangePassword *tempVar7 = new S::ChangePassword();
            tempVar7->Result = 5;
            c->Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        account->Password = p->NewPassword;
        S::ChangePassword *tempVar8 = new S::ChangePassword();
        tempVar8->Result = 6;
        c->Enqueue(tempVar8);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::Login(ClientPackets::Login *p, MirConnection *c)
    {
        if (!Settings::AllowLogin)
        {
            S::Login *tempVar = new S::Login();
            tempVar->Result = 0;
            c->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!AccountIDReg->IsMatch(p->AccountID))
        {
            S::Login *tempVar2 = new S::Login();
            tempVar2->Result = 1;
            c->Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!PasswordReg->IsMatch(p->Password))
        {
            S::Login *tempVar3 = new S::Login();
            tempVar3->Result = 2;
            c->Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            return;
        }
        auto account = GetAccount(p->AccountID);

        if (account == nullptr)
        {
            S::Login *tempVar4 = new S::Login();
            tempVar4->Result = 3;
            c->Enqueue(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (account->Banned)
        {
            if (account->ExpiryDate > DateTime::Now)
            {
                S::LoginBanned *tempVar5 = new S::LoginBanned();
                tempVar5->Reason = account->BanReason;
                tempVar5->ExpiryDate = account->ExpiryDate;
                c->Enqueue(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
                return;
            }
            account->Banned = false;
        }
            account->BanReason = "";
            account->ExpiryDate = DateTime::MinValue;


        if (account->Password.compare(p->Password) != 0)
        {
            if (account->WrongPasswordCount++ >= 5)
            {
                account->Banned = true;
                account->BanReason = "Too many Wrong Login Attempts.";
                account->ExpiryDate = DateTime::Now.AddMinutes(2);

                S::LoginBanned *tempVar6 = new S::LoginBanned();
                tempVar6->Reason = account->BanReason;
                tempVar6->ExpiryDate = account->ExpiryDate;
                c->Enqueue(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
                return;
            }

            S::Login *tempVar7 = new S::Login();
            tempVar7->Result = 4;
            c->Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
            return;
        }
        account->WrongPasswordCount = 0;

        {
            std::scoped_lock<std::mutex> lock(AccountLock);
            if (account->Connection != nullptr)
            {
                account->Connection->SendDisconnect(1);
            }

            account->Connection = c;
        }

        c->Account = account;
        c->Stage = GameStage::Select;

        account->LastDate = getNow();
        account->LastIP = c->IPAddress;

        getMessageQueue()->Enqueue(std::to_string(account->Connection->SessionID) + ", " + account->Connection->IPAddress + ", User logged in.");
        S::LoginSuccess *tempVar8 = new S::LoginSuccess();
        tempVar8->Characters = account->GetSelectInfo();
        c->Enqueue(tempVar8);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
    }

    int Envir::HTTPLogin(const std::string &AccountID, const std::string &Password)
    {
        if (!Settings::AllowLogin)
        {
            return 0;
        }

        if (!AccountIDReg->IsMatch(AccountID))
        {
            return 1;
        }

        if (!PasswordReg->IsMatch(Password))
        {
            return 2;
        }

        auto account = GetAccount(AccountID);

        if (account == nullptr)
        {
            return 3;
        }

        if (account->Banned)
        {
            if (account->ExpiryDate > DateTime::Now)
            {
                return 4;
            }
            account->Banned = false;
        }
        account->BanReason = "";
        account->ExpiryDate = DateTime::MinValue;
        if (account->Password.compare(Password) != 0)
        {
            if (account->WrongPasswordCount++ >= 5)
            {
                account->Banned = true;
                account->BanReason = "Too many Wrong Login Attempts.";
                account->ExpiryDate = DateTime::Now.AddMinutes(2);
                return 5;
            }
            return 6;
        }
        account->WrongPasswordCount = 0;
        return 7;
    }

    void Envir::NewCharacter(ClientPackets::NewCharacter *p, MirConnection *c, bool IsGm)
    {
        if (!Settings::AllowNewCharacter)
        {
            S::NewCharacter *tempVar = new S::NewCharacter();
            tempVar->Result = 0;
            c->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!CharacterReg->IsMatch(p->Name))
        {
            S::NewCharacter *tempVar2 = new S::NewCharacter();
            tempVar2->Result = 1;
            c->Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (!IsGm && std::find(DisabledCharNames.begin(), DisabledCharNames.end(), StringHelper::toUpper(p->Name) != DisabledCharNames.end()))
        {
            S::NewCharacter *tempVar3 = new S::NewCharacter();
            tempVar3->Result = 1;
            c->Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (p->Gender != MirGender::Male && p->Gender != MirGender::Female)
        {
            S::NewCharacter *tempVar4 = new S::NewCharacter();
            tempVar4->Result = 2;
            c->Enqueue(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (p->Class != MirClass::Warrior && p->Class != MirClass::Wizard && p->Class != MirClass::Taoist && p->Class != MirClass::Assassin && p->Class != MirClass::Archer)
        {
            S::NewCharacter *tempVar5 = new S::NewCharacter();
            tempVar5->Result = 3;
            c->Enqueue(tempVar5);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (p->Class == MirClass::Assassin && !Settings::AllowCreateAssassin || p->Class == MirClass::Archer && !Settings::AllowCreateArcher)
        {
            S::NewCharacter *tempVar6 = new S::NewCharacter();
            tempVar6->Result = 3;
            c->Enqueue(tempVar6);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        auto count = 0;

        for (auto i = 0; i < c->Account->Characters.size(); i++)
        {
            if (c->Account->Characters[i]->Deleted)
            {
                continue;
            }

            if (++count >= Globals::MaxCharacterCount)
            {
                S::NewCharacter *tempVar7 = new S::NewCharacter();
                tempVar7->Result = 4;
                c->Enqueue(tempVar7);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
                return;
            }
        }

        {
            std::scoped_lock<std::mutex> lock(AccountLock);
            if (CharacterExists(p->Name))
            {
                S::NewCharacter *tempVar8 = new S::NewCharacter();
                tempVar8->Result = 5;
                c->Enqueue(tempVar8);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
                return;
            }

            auto info = new CharacterInfo(p, c);
            info->Index = ++NextCharacterID;
            info->AccountInfo = c->Account;

            c->Account->Characters.push_back(info);
            CharacterList.push_back(info);

            S::NewCharacterSuccess *tempVar9 = new S::NewCharacterSuccess();
            tempVar9->CharInfo = info->ToSelectInfo();
            c->Enqueue(tempVar9);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar9' statement was not added since tempVar9 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete info' statement was not added since info was passed to a method or constructor. Handle memory management manually.
        }
    }

    bool Envir::AccountExists(const std::string &accountID)
    {
            for (auto i = 0; i < AccountList.size(); i++)
            {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
                if (std::string::Compare(AccountList[i]->AccountID, accountID, StringComparison::OrdinalIgnoreCase) == 0)
                {
                    return true;
                }
            }

            return false;
    }

    bool Envir::CharacterExists(const std::string &name)
    {
        for (auto i = 0; i < CharacterList.size(); i++)
        {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
            if (std::string::Compare(CharacterList[i]->Name, name, StringComparison::OrdinalIgnoreCase) == 0)
            {
                return true;
            }
        }

        return false;
    }

    AccountInfo *Envir::GetAccount(const std::string &accountID)
    {
            for (auto i = 0; i < AccountList.size(); i++)
            {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
                if (std::string::Compare(AccountList[i]->AccountID, accountID, StringComparison::OrdinalIgnoreCase) == 0)
                {
                    return AccountList[i];
                }
            }

            return nullptr;
    }

    std::vector<AccountInfo*> Envir::MatchAccounts(const std::string &accountID, bool match)
    {
        if (accountID.empty())
        {
            return std::vector<AccountInfo*>(AccountList);
        }

        auto list = std::vector<AccountInfo*>();

        for (auto i = 0; i < AccountList.size(); i++)
        {
            if (match)
            {
//C# TO C++ CONVERTER TODO TASK: The following .NET 'String.Equals' reference is not converted:
                if (AccountList[i]->AccountID->Equals(accountID, StringComparison::OrdinalIgnoreCase))
                {
                    list.push_back(AccountList[i]);
                }
            }
            else
            {
                if (AccountList[i]->AccountID.find(accountID, StringComparison::OrdinalIgnoreCase) != std::string::npos)
                {
                    list.push_back(AccountList[i]);
                }
            }
        }

        return list;
    }

    std::vector<AccountInfo*> Envir::MatchAccountsByPlayer(const std::string &playerName, bool match)
    {
        if (playerName.empty())
        {
            return std::vector<AccountInfo*>(AccountList);
        }

        auto list = std::vector<AccountInfo*>();

        for (auto i = 0; i < AccountList.size(); i++)
        {
            for (auto j = 0; j < AccountList[i]->Characters.size(); j++)
            {
                if (match)
                {
//C# TO C++ CONVERTER TODO TASK: The following .NET 'String.Equals' reference is not converted:
                    if (AccountList[i]->Characters[j]->Name.Equals(playerName, StringComparison::OrdinalIgnoreCase))
                    {
                        list.push_back(AccountList[i]);
                    }
                }
                else
                {
                    if (AccountList[i]->Characters[j]->Name.find(playerName, StringComparison::OrdinalIgnoreCase) != std::string::npos)
                    {
                        list.push_back(AccountList[i]);
                    }
                }
            }
        }

        return list;
    }

    void Envir::CreateAccountInfo()
    {
        AccountInfo *tempVar = new AccountInfo();
        tempVar->Index = ++NextAccountID;
        AccountList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::CreateMapInfo()
    {
        MapInfo *tempVar = new MapInfo();
        tempVar->Index = ++MapIndex;
        MapInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::CreateItemInfo(ItemType type)
    {
        ItemInfo *tempVar = new ItemInfo();
        tempVar->Index = ++ItemIndex;
        tempVar->Type = type;
        tempVar->RandomStatsId = 255;
        ItemInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::CreateMonsterInfo()
    {
        MonsterInfo *tempVar = new MonsterInfo();
        tempVar->Index = ++MonsterIndex;
        MonsterInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::CreateNPCInfo()
    {
        NPCInfo *tempVar = new NPCInfo();
        tempVar->Index = ++NPCIndex;
        NPCInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::CreateQuestInfo()
    {
        QuestInfo *tempVar = new QuestInfo();
        tempVar->Index = ++QuestIndex;
        QuestInfoList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::AddToGameShop(ItemInfo *Info)
    {
        GameShopItem *tempVar = new GameShopItem();
        tempVar->GIndex = ++GameshopIndex;
        tempVar->GoldPrice = static_cast<unsigned int>(1000 * Settings::CredxGold);
        tempVar->CreditPrice = 1000;
        tempVar->ItemIndex = Info->Index;
        tempVar->Info = Info;
        tempVar->Date = DateTime::Now;
        tempVar->Class = "All";
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
        tempVar->Category = Info->Type.ToString();
        GameShopList.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void Envir::Remove(MapInfo *info)
    {
        MapInfoList.Remove(info);
        //Desync all objects\
    }

    void Envir::Remove(ItemInfo *info)
    {
        ItemInfoList.Remove(info);
    }

    void Envir::Remove(MonsterInfo *info)
    {
        MonsterInfoList.Remove(info);
        //Desync all objects\
    }

    void Envir::Remove(NPCInfo *info)
    {
        NPCInfoList.Remove(info);
        //Desync all objects\
    }

    void Envir::Remove(QuestInfo *info)
    {
        QuestInfoList.Remove(info);
        //Desync all objects\
    }

    void Envir::Remove(GameShopItem *info)
    {
        GameShopList.Remove(info);

        if (GameShopList.empty())
        {
            GameshopIndex = 0;
        }

        //Desync all objects\
    }

    UserItem *Envir::CreateFreshItem(ItemInfo *info)
    {
        auto item = new UserItem(info);
        item->UniqueID = ++NextUserItemID;
        item->CurrentDura = info->Durability;
        item->MaxDura = info->Durability;

        UpdateItemExpiry(item);

//C# TO C++ CONVERTER TODO TASK: A 'delete item' statement was not added since item was passed to a method or constructor. Handle memory management manually.
        return item;
    }

    UserItem *Envir::CreateDropItem(int index)
    {
        return CreateDropItem(GetItemInfo(index));
    }

    UserItem *Envir::CreateDropItem(ItemInfo *info)
    {
        if (info == nullptr)
        {
            return nullptr;
        }

        auto item = new UserItem(info);
        item->UniqueID = ++NextUserItemID;
        item->MaxDura = info->Durability;
        item->CurrentDura = static_cast<unsigned short>(std::min(info->Durability, Random->Next(info->Durability) + 1000));

        UpgradeItem(item);

        UpdateItemExpiry(item);

        if (!info->NeedIdentify)
        {
            item->Identified = true;
        }

//C# TO C++ CONVERTER TODO TASK: A 'delete item' statement was not added since item was passed to a method or constructor. Handle memory management manually.
        return item;
    }

    UserItem *Envir::CreateShopItem(ItemInfo *info, unsigned long long id)
    {
        if (info == nullptr)
        {
            return nullptr;
        }

        auto item = new UserItem(info);
        item->UniqueID = id;
        item->CurrentDura = info->Durability;
        item->MaxDura = info->Durability;
        item->IsShopItem = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete item' statement was not added since item was used in a 'return' or 'throw' statement.
        return item;
    }

    void Envir::UpdateItemExpiry(UserItem *item)
    {
        auto expiryInfo = new ExpireInfo();

        auto r = new Regex(R"(\[(.*?)\])");
        auto expiryMatch = r->Match(item->Info->Name);

        if (expiryMatch->Success)
        {
            auto parameter = expiryMatch->Groups[1]->Captures[0]->Value;

            auto numAlpha = new Regex("(?<Numeric>[0-9]*)(?<Alpha>[a-zA-Z]*)");
            auto match = numAlpha->Match(parameter);

            auto alpha = match->Groups["Alpha"]->Value;
            auto num = 0;

            int::TryParse(match->Groups["Numeric"]->Value, num);

//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string and was converted to C++ 'if-else' logic:
//            switch (alpha)
//ORIGINAL LINE: case "m":
            if (alpha == "m")
            {
                    expiryInfo->ExpiryDate = DateTime::Now.AddMinutes(num);
            }
//ORIGINAL LINE: case "h":
            else if (alpha == "h")
            {
                    expiryInfo->ExpiryDate = DateTime::Now.AddHours(num);
            }
//ORIGINAL LINE: case "d":
            else if (alpha == "d")
            {
                    expiryInfo->ExpiryDate = DateTime::Now.AddDays(num);
            }
//ORIGINAL LINE: case "M":
            else if (alpha == "M")
            {
                    expiryInfo->ExpiryDate = DateTime::Now.AddMonths(num);
            }
//ORIGINAL LINE: case "y":
            else if (alpha == "y")
            {
                    expiryInfo->ExpiryDate = DateTime::Now.AddYears(num);
            }
            else
            {
                    expiryInfo->ExpiryDate = DateTime::MaxValue;
            }

            item->ExpireInfo = expiryInfo;

            delete numAlpha;
        }

        delete r;
//C# TO C++ CONVERTER TODO TASK: A 'delete expiryInfo' statement was not added since expiryInfo was assigned to a field. Handle memory management manually.
    }

    void Envir::UpgradeItem(UserItem *item)
    {
        if (item->Info->RandomStats == nullptr)
        {
            return;
        }
        auto stat = item->Info->RandomStats;
        if (stat->MaxDuraChance > 0 && Random->Next(stat->MaxDuraChance) == 0)
        {
            auto dura = RandomomRange(stat->MaxDuraMaxStat, stat->MaxDuraStatChance);
            item->MaxDura = static_cast<unsigned short>(std::min(std::numeric_limits<unsigned short>::max(), item->MaxDura + dura * 1000));
            item->CurrentDura = static_cast<unsigned short>(std::min(std::numeric_limits<unsigned short>::max(), item->CurrentDura + dura * 1000));
        }

        if (stat->MaxAcChance > 0 && Random->Next(stat->MaxAcChance) == 0)
        {
            item->AddedStats[Stat::MaxAC] = static_cast<unsigned char>(RandomomRange(stat->MaxAcMaxStat - 1, stat->MaxAcStatChance) + 1);
        }
        if (stat->MaxMacChance > 0 && Random->Next(stat->MaxMacChance) == 0)
        {
            item->AddedStats[Stat::MaxMAC] = static_cast<unsigned char>(RandomomRange(stat->MaxMacMaxStat - 1, stat->MaxMacStatChance) + 1);
        }
        if (stat->MaxDcChance > 0 && Random->Next(stat->MaxDcChance) == 0)
        {
            item->AddedStats[Stat::MaxDC] = static_cast<unsigned char>(RandomomRange(stat->MaxDcMaxStat - 1, stat->MaxDcStatChance) + 1);
        }
        if (stat->MaxMcChance > 0 && Random->Next(stat->MaxMcChance) == 0)
        {
            item->AddedStats[Stat::MaxMC] = static_cast<unsigned char>(RandomomRange(stat->MaxMcMaxStat - 1, stat->MaxMcStatChance) + 1);
        }
        if (stat->MaxScChance > 0 && Random->Next(stat->MaxScChance) == 0)
        {
            item->AddedStats[Stat::MaxSC] = static_cast<unsigned char>(RandomomRange(stat->MaxScMaxStat - 1, stat->MaxScStatChance) + 1);
        }
        if (stat->AccuracyChance > 0 && Random->Next(stat->AccuracyChance) == 0)
        {
            item->AddedStats[Stat::Accuracy] = static_cast<unsigned char>(RandomomRange(stat->AccuracyMaxStat - 1, stat->AccuracyStatChance) + 1);
        }
        if (stat->AgilityChance > 0 && Random->Next(stat->AgilityChance) == 0)
        {
            item->AddedStats[Stat::Agility] = static_cast<unsigned char>(RandomomRange(stat->AgilityMaxStat - 1, stat->AgilityStatChance) + 1);
        }
        if (stat->HpChance > 0 && Random->Next(stat->HpChance) == 0)
        {
            item->AddedStats[Stat::HP] = static_cast<unsigned char>(RandomomRange(stat->HpMaxStat - 1, stat->HpStatChance) + 1);
        }
        if (stat->MpChance > 0 && Random->Next(stat->MpChance) == 0)
        {
            item->AddedStats[Stat::MP] = static_cast<unsigned char>(RandomomRange(stat->MpMaxStat - 1, stat->MpStatChance) + 1);
        }
        if (stat->StrongChance > 0 && Random->Next(stat->StrongChance) == 0)
        {
            item->AddedStats[Stat::Strong] = static_cast<unsigned char>(RandomomRange(stat->StrongMaxStat - 1, stat->StrongStatChance) + 1);
        }
        if (stat->MagicResistChance > 0 && Random->Next(stat->MagicResistChance) == 0)
        {
            item->AddedStats[Stat::MagicResist] = static_cast<unsigned char>(RandomomRange(stat->MagicResistMaxStat - 1, stat->MagicResistStatChance) + 1);
        }
        if (stat->PoisonResistChance > 0 && Random->Next(stat->PoisonResistChance) == 0)
        {
            item->AddedStats[Stat::PoisonResist] = static_cast<unsigned char>(RandomomRange(stat->PoisonResistMaxStat - 1, stat->PoisonResistStatChance) + 1);
        }
        if (stat->HpRecovChance > 0 && Random->Next(stat->HpRecovChance) == 0)
        {
            item->AddedStats[Stat::HealthRecovery] = static_cast<unsigned char>(RandomomRange(stat->HpRecovMaxStat - 1, stat->HpRecovStatChance) + 1);
        }
        if (stat->MpRecovChance > 0 && Random->Next(stat->MpRecovChance) == 0)
        {
            item->AddedStats[Stat::SpellRecovery] = static_cast<unsigned char>(RandomomRange(stat->MpRecovMaxStat - 1, stat->MpRecovStatChance) + 1);
        }
        if (stat->PoisonRecovChance > 0 && Random->Next(stat->PoisonRecovChance) == 0)
        {
            item->AddedStats[Stat::PoisonRecovery] = static_cast<unsigned char>(RandomomRange(stat->PoisonRecovMaxStat - 1, stat->PoisonRecovStatChance) + 1);
        }
        if (stat->CriticalRateChance > 0 && Random->Next(stat->CriticalRateChance) == 0)
        {
            item->AddedStats[Stat::CriticalRate] = static_cast<unsigned char>(RandomomRange(stat->CriticalRateMaxStat - 1, stat->CriticalRateStatChance) + 1);
        }
        if (stat->CriticalDamageChance > 0 && Random->Next(stat->CriticalDamageChance) == 0)
        {
            item->AddedStats[Stat::CriticalDamage] = static_cast<unsigned char>(RandomomRange(stat->CriticalDamageMaxStat - 1, stat->CriticalDamageStatChance) + 1);
        }
        if (stat->FreezeChance > 0 && Random->Next(stat->FreezeChance) == 0)
        {
            item->AddedStats[Stat::Freezing] = static_cast<unsigned char>(RandomomRange(stat->FreezeMaxStat - 1, stat->FreezeStatChance) + 1);
        }
        if (stat->PoisonAttackChance > 0 && Random->Next(stat->PoisonAttackChance) == 0)
        {
            item->AddedStats[Stat::PoisonAttack] = static_cast<unsigned char>(RandomomRange(stat->PoisonAttackMaxStat - 1, stat->PoisonAttackStatChance) + 1);
        }
        if (stat->AttackSpeedChance > 0 && Random->Next(stat->AttackSpeedChance) == 0)
        {
            item->AddedStats[Stat::AttackSpeed] = static_cast<signed char>(RandomomRange(stat->AttackSpeedMaxStat - 1, stat->AttackSpeedStatChance) + 1);
        }
        if (stat->LuckChance > 0 && Random->Next(stat->LuckChance) == 0)
        {
            item->AddedStats[Stat::Luck] = static_cast<signed char>(RandomomRange(stat->LuckMaxStat - 1, stat->LuckStatChance) + 1);
        }
        if (stat->CurseChance > 0 && Random->Next(100) <= stat->CurseChance)
        {
            item->Cursed = true;
        }

        if (stat->SlotChance > 0 && Random->Next(stat->SlotChance) == 0)
        {
            auto slot = static_cast<unsigned char>(RandomomRange(stat->SlotMaxStat - 1, stat->SlotStatChance) + 1);

            if (slot > item->Info->Slots)
            {
                item->SetSlotSize(std::make_optional(slot));
            }
        }
    }

    int Envir::RandomomRange(int count, int rate)
    {
        auto x = 0;
        for (auto i = 0; i < count; i++)
        {
            if (Random->Next(rate) == 0)
            {
                x++;
            }
        }
        return x;
    }

    bool Envir::BindItem(UserItem *item)
    {
        for (auto i = 0; i < ItemInfoList.size(); i++)
        {
            auto info = ItemInfoList[i];
            if (info->Index != item->ItemIndex)
            {
                continue;
            }
            item->Info = info;

            return BindSlotItems(item);
        }
        return false;
    }

    bool Envir::BindGameShop(GameShopItem *item, bool editEnvir)
    {
        for (auto i = 0; i < getEdit()->ItemInfoList.size(); i++)
        {
            auto info = getEdit()->ItemInfoList[i];
            if (info->Index != item->ItemIndex)
            {
                continue;
            }
            item->Info = info;

            return true;
        }
        return false;
    }

    bool Envir::BindSlotItems(UserItem *item)
    {
        for (auto i = 0; i < item->Slots.size(); i++)
        {
            if (item->Slots[i] == nullptr)
            {
                continue;
            }

            if (!BindItem(item->Slots[i]))
            {
                return false;
            }
        }

        return true;
    }

    bool Envir::BindQuest(QuestProgressInfo *quest)
    {
        for (auto i = 0; i < QuestInfoList.size(); i++)
        {
            auto info = QuestInfoList[i];
            if (info->Index != quest->Index)
            {
                continue;
            }
            quest->Info = info;
            return true;
        }
        return false;
    }

    Map *Envir::GetMap(int index)
    {
        return MapList.FirstOrDefault([&] (std::any t)
        {
            return t::Info->Index == index;
        });
    }

    Map *Envir::GetMapByNameAndInstance(const std::string &name, int instanceValue)
    {
        if (instanceValue < 0)
        {
            instanceValue = 0;
        }
        if (instanceValue > 0)
        {
            instanceValue--;
        }

        auto instanceMapList = MapList.Where([&] (std::any t)
        {
            return std::string::Equals(t::Info::FileName, name, StringComparison::CurrentCultureIgnoreCase);
        }).ToList();
        return instanceValue < instanceMapList.size()() ? instanceMapList[instanceValue] : nullptr;
    }

    MonsterInfo *Envir::GetMonsterInfo(int index)
    {
        for (auto i = 0; i < MonsterInfoList.size(); i++)
        {
            if (MonsterInfoList[i]->Index == index)
            {
                return MonsterInfoList[i];
            }
        }

        return nullptr;
    }

    MonsterInfo *Envir::GetMonsterInfo(int ai, int effect)
    {
        for (auto i = 0; i < MonsterInfoList.size(); i++)
        {
            if (MonsterInfoList[i]->AI == ai && (MonsterInfoList[i]->Effect == effect || effect < 0))
            {
                return MonsterInfoList[i];
            }
        }

        return nullptr;
    }

    NPCObject *Envir::GetNPC(const std::string &name)
    {
        return MapList.SelectMany([&] (std::any t1)
        {
            t1::NPCs::Where([&] (std::any t)
            {
                return t::Info->Name == name;
            });
        }).FirstOrDefault();
    }

    MonsterInfo *Envir::GetMonsterInfo(const std::string &name, bool Strict)
    {
        for (auto i = 0; i < MonsterInfoList.size(); i++)
        {
            auto info = MonsterInfoList[i];
            if (Strict)
            {
                if (info->Name != name)
                {
                    continue;
                }
                return info;
            }
            else
            {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
                if (std::string::Compare(info->Name, name, StringComparison::OrdinalIgnoreCase) != 0 && std::string::Compare(StringHelper::replace(info->Name, " ", ""), StringHelper::replace(name, " ", ""), StringComparison::OrdinalIgnoreCase) != 0)
                {
                    continue;
                }
                return info;
            }
        }
        return nullptr;
    }

    PlayerObject *Envir::GetPlayer(const std::string &name)
    {
        for (auto i = 0; i < Players.size(); i++)
        {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
            if (std::string::Compare(Players[i]->getName(), name, StringComparison::OrdinalIgnoreCase) == 0)
            {
                return Players[i];
            }
        }

        return nullptr;
    }

    PlayerObject *Envir::GetPlayer(unsigned int PlayerId)
    {
        for (auto i = 0; i < Players.size(); i++)
        {
            if (Players[i]->Info->Index == PlayerId)
            {
                return Players[i];
            }
        }

        return nullptr;
    }

    CharacterInfo *Envir::GetCharacterInfo(const std::string &name)
    {
        for (auto i = 0; i < CharacterList.size(); i++)
        {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
            if (std::string::Compare(CharacterList[i]->Name, name, StringComparison::OrdinalIgnoreCase) == 0)
            {
                return CharacterList[i];
            }
        }

        return nullptr;
    }

    CharacterInfo *Envir::GetCharacterInfo(int index)
    {
        for (auto i = 0; i < CharacterList.size(); i++)
        {
            if (CharacterList[i]->Index == index)
            {
                return CharacterList[i];
            }
        }

        return nullptr;
    }

    ItemInfo *Envir::GetItemInfo(int index)
    {
        for (auto i = 0; i < ItemInfoList.size(); i++)
        {
            auto info = ItemInfoList[i];
            if (info->Index != index)
            {
                continue;
            }
            return info;
        }
        return nullptr;
    }

    ItemInfo *Envir::GetItemInfo(const std::string &name)
    {
        for (auto i = 0; i < ItemInfoList.size(); i++)
        {
            auto info = ItemInfoList[i];
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
            if (std::string::Compare(StringHelper::replace(info->Name, " ", ""), name, StringComparison::OrdinalIgnoreCase) != 0)
            {
                continue;
            }
            return info;
        }
        return nullptr;
    }

    QuestInfo *Envir::GetQuestInfo(int index)
    {
        return QuestInfoList.FirstOrDefault([&] (std::any info)
        {
            return info->Index == index;
        });
    }

    ItemInfo *Envir::GetBook(short Skill)
    {
        for (auto i = 0; i < ItemInfoList.size(); i++)
        {
            auto info = ItemInfoList[i];
            if (info->Type != ItemType::Book || info->Shape != Skill)
            {
                continue;
            }
            return info;
        }
        return nullptr;
    }

    void Envir::MessageAccount(AccountInfo *account, const std::string &message, ChatType type)
    {
        if (account == nullptr ? nullptr : account->Characters.empty())
        {
            return;
        }

        for (auto i = 0; i < account->Characters.size(); i++)
        {
            if (account->Characters[i]->Player == nullptr)
            {
                continue;
            }
            account->Characters[i]->Player.ReceiveChat(message, type);
            return;
        }
    }

    void Envir::MailCharacter(CharacterInfo *info, UserItem *item, unsigned int gold, int reason, const std::string &customMessage)
    {
        std::string sender = "Bichon Administrator";

        std::string message = "You have been mailed due to the following reason:\r\n\r\n";

        switch (reason)
        {
            case 1:
                message += "Could not return item to bag after trade.";
                break;
            case 99:
                message += "Code didn't correctly handle checking inventory space.";
                break;
            default:
                message += (customMessage != "") ? customMessage : "No reason provided.";
                break;
        }

        MailInfo *mail = new MailInfo(info->Index);
        mail->Sender = sender;
        mail->Message = message;
        mail->Gold = gold;

        if (item != nullptr)
        {
            mail->Items.push_back(item);
        }

        mail->Send();

        delete mail;
    }

    GuildObject *Envir::GetGuild(const std::string &name)
    {
        for (auto i = 0; i < GuildList.size(); i++)
        {
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
            if (std::string::Compare(StringHelper::replace(GuildList[i]->Name, " ", ""), name, StringComparison::OrdinalIgnoreCase) != 0)
            {
                continue;
            }
            return GuildList[i];
        }
        return nullptr;
    }

    GuildObject *Envir::GetGuild(int index)
    {
        for (auto i = 0; i < GuildList.size(); i++)
        {
            if (GuildList[i]->Guildindex == index)
            {
                return GuildList[i];
            }
        }
        return nullptr;
    }

    void Envir::ProcessNewDay()
    {
        for (auto c : CharacterList)
        {
            ClearDailyQuests(c);

            c->NewDay = true;

            if (c->Player != nullptr)
            {
                c->Player->CallDefaultNPC(DefaultNPCType::Daily);
            }
        }
    }

    void Envir::ProcessRentedItems()
    {
        for (auto characterInfo : CharacterList)
        {
            if (characterInfo->RentedItems.size() <= 0)
            {
                continue;
            }

            for (auto rentedItemInfo : *characterInfo->RentedItems)
            {
                if (rentedItemInfo->ItemReturnDate >= getNow())
                {
                    continue;
                }

                auto rentingPlayer = GetCharacterInfo(rentedItemInfo->RentingPlayerName);

                for (auto i = 0; i < rentingPlayer->Inventory.size(); i++)
                {
                    if (rentedItemInfo->ItemId != rentingPlayer == nullptr ? nullptr : (rentingPlayer->Inventory[i] == nullptr ? nullptr : rentingPlayer->Inventory[i]->UniqueID))
                    {
                        continue;
                    }

                    auto item = rentingPlayer->Inventory[i];

                    if (item == nullptr ? nullptr : item->RentalInformation == nullptr)
                    {
                        continue;
                    }

                    if (getNow() <= item->RentalInformation->ExpiryDate)
                    {
                        continue;
                    }

                    ReturnRentalItem(item, item->RentalInformation->OwnerName, rentingPlayer, false);
                    rentingPlayer->Inventory[i] = nullptr;
                    rentingPlayer->HasRentedItem = false;

                    if (rentingPlayer->Player == nullptr)
                    {
                        continue;
                    }

                    rentingPlayer->Player->ReceiveChat(StringHelper::formatSimple("{0} has just expired from your inventory.", item->Info->getFriendlyName()), ChatType::Hint);
                    S::DeleteItem *tempVar = new S::DeleteItem();
                    tempVar->UniqueID = item->UniqueID;
                    tempVar->Count = item->Count;
                    rentingPlayer->Player->Enqueue(tempVar);
                    rentingPlayer->Player->RefreshStats();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }

                for (auto i = 0; i < rentingPlayer->Equipment.size(); i++)
                {
                    auto item = rentingPlayer->Equipment[i];

                    if (item == nullptr ? nullptr : item->RentalInformation == nullptr)
                    {
                        continue;
                    }

                    if (getNow() <= item->RentalInformation->ExpiryDate)
                    {
                        continue;
                    }

                    ReturnRentalItem(item, item->RentalInformation->OwnerName, rentingPlayer, false);
                    rentingPlayer->Equipment[i] = nullptr;
                    rentingPlayer->HasRentedItem = false;

                    if (rentingPlayer->Player == nullptr)
                    {
                        continue;
                    }

                    rentingPlayer->Player->ReceiveChat(StringHelper::formatSimple("{0} has just expired from your inventory.", item->Info->getFriendlyName()), ChatType::Hint);
                    S::DeleteItem *tempVar2 = new S::DeleteItem();
                    tempVar2->UniqueID = item->UniqueID;
                    tempVar2->Count = item->Count;
                    rentingPlayer->Player->Enqueue(tempVar2);
                    rentingPlayer->Player->RefreshStats();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                }
            }
        }

        for (auto characterInfo : CharacterList)
        {
            if (characterInfo->RentedItemsToRemove.size() <= 0)
            {
                continue;
            }

            for (auto rentalInformationToRemove : *characterInfo->RentedItemsToRemove)
            {
                characterInfo->RentedItems.Remove(rentalInformationToRemove);
            }

            characterInfo->RentedItemsToRemove.clear();
        }
    }

    bool Envir::ReturnRentalItem(UserItem *rentedItem, const std::string &ownerName, CharacterInfo *rentingCharacterInfo, bool removeNow)
    {
        if (rentedItem->RentalInformation == nullptr)
        {
            return false;
        }

        auto owner = GetCharacterInfo(ownerName);
        auto returnItems = std::vector<UserItem*>();

        for (auto rentalInformation : *owner->RentedItems)
        {
            if (rentalInformation->ItemId == rentedItem->UniqueID)
            {
                owner->RentedItemsToRemove.push_back(rentalInformation);
            }
        }

        rentedItem->RentalInformation->BindingFlags = BindMode::None;
        rentedItem->RentalInformation->RentalLocked = true;
        rentedItem->RentalInformation->ExpiryDate = rentedItem->RentalInformation->ExpiryDate.AddDays(1);

        returnItems.push_back(rentedItem);

        auto mail = new MailInfo(owner->Index, true);
        mail->Sender = rentingCharacterInfo->Name;
        mail->Message = rentedItem->Info->getFriendlyName();
        mail->Items = returnItems;

        mail->Send();

        if (removeNow)
        {
            for (auto rentalInformationToRemove : *owner->RentedItemsToRemove)
            {
                owner->RentedItems.Remove(rentalInformationToRemove);
            }

            owner->RentedItemsToRemove.clear();
        }

        delete mail;
        return true;
    }

    void Envir::ClearDailyQuests(CharacterInfo *info)
    {
        for (auto quest : QuestInfoList)
        {
            if (quest->Type != QuestType::Daily)
            {
                continue;
            }

            for (auto i = 0; i < info->CompletedQuests.size(); i++)
            {
                if (info->CompletedQuests[i] != quest->Index)
                {
                    continue;
                }

                info->CompletedQuests.erase(info->CompletedQuests.begin() + i);
            }
        }

        if (info->Player != nullptr)
        {
            info->Player->GetCompletedQuests();
        }
    }

    GuildBuffInfo *Envir::FindGuildBuffInfo(int Id)
    {
        for (auto i = 0; i < Settings::Guild_BuffList.size(); i++)
        {
            if (Settings::Guild_BuffList[i]->Id == Id)
            {
                return Settings::Guild_BuffList[i];
            }
        }
        return nullptr;
    }

    void Envir::ClearGameshopLog()
    {
        getMain()->GameshopLog.clear();

        for (auto i = 0; i < AccountList.size(); i++)
        {
            for (auto f = 0; f < AccountList[i]->Characters.size(); f++)
            {
                AccountList[i]->Characters[f].GSpurchases->clear();
            }
        }

        ResetGS = false;
        getMessageQueue()->Enqueue("Gameshop Purchase Logs Cleared.");
    }

    int Envir::InsertRank(std::vector<RankCharacterInfo*> &Ranking, RankCharacterInfo *NewRank)
    {
        if (Ranking.empty())
        {
            Ranking.push_back(NewRank);
            return Ranking.size();
        }

        for (auto i = 0; i < Ranking.size(); i++)
        {
            //if level is lower
            if (Ranking[i]->level < NewRank->level)
            {
                Ranking.Insert(i, NewRank);
                return i + 1;
            }

            //if exp is lower but level = same
            if (Ranking[i]->level == NewRank->level && Ranking[i]->Experience < NewRank->Experience)
            {
                Ranking.Insert(i, NewRank);
                return i + 1;
            }
        }

        if (Ranking.size() < RankCount)
        {
            Ranking.push_back(NewRank);
            return Ranking.size();
        }

        return 0;
    }

    bool Envir::TryAddRank(std::vector<RankCharacterInfo*> &Ranking, CharacterInfo *info, unsigned char type)
    {
        auto NewRank = new RankCharacterInfo();
        NewRank->Name = info->Name;
        NewRank->Class = info->Class;
        NewRank->Experience = info->Experience;
        NewRank->level = info->Level;
        NewRank->PlayerId = info->Index;
        NewRank->info = info;
        auto NewRankIndex = InsertRank(Ranking, NewRank);
        if (NewRankIndex == 0)
        {
//C# TO C++ CONVERTER TODO TASK: A 'delete NewRank' statement was not added since NewRank was passed to a method or constructor. Handle memory management manually.
            return false;
        }
        for (auto i = NewRankIndex; i < Ranking.size(); i++)
        {
            SetNewRank(Ranking[i], i + 1, type);
        }
        info->Rank[type] = NewRankIndex;

//C# TO C++ CONVERTER TODO TASK: A 'delete NewRank' statement was not added since NewRank was passed to a method or constructor. Handle memory management manually.
        return true;
    }

    int Envir::FindRank(std::vector<RankCharacterInfo*> &Ranking, CharacterInfo *info, unsigned char type)
    {
        auto startindex = info->Rank[type];
        if (startindex > 0) //if there's a previously known rank then the user can only have gone down in the ranking (or stayed the same)
        {
            for (auto i = startindex - 1; i < Ranking.size(); i++)
            {
                if (Ranking[i]->Name == info->Name)
                {
                    return i;
                }
            }
            info->Rank[type] = 0; //set the rank to 0 to tell future searches it's not there anymore
        }
        return -1; //index can be 0
    }

    bool Envir::UpdateRank(std::vector<RankCharacterInfo*> &Ranking, CharacterInfo *info, unsigned char type)
    {
        auto CurrentRank = FindRank(Ranking, info, type);
        if (CurrentRank == -1)
        {
            return false; //not in ranking list atm
        }

        auto NewRank = CurrentRank;
        //next find our updated rank
        for (auto i = CurrentRank - 1; i >= 0; i--)
        {
            if (Ranking[i]->level > info->Level || Ranking[i]->level == info->Level && Ranking[i]->Experience > info->Experience)
            {
                break;
            }
                NewRank = i;
        }

        Ranking[CurrentRank]->level = info->Level;
        Ranking[CurrentRank]->Experience = info->Experience;

        if (NewRank < CurrentRank)
        { //if we gained any ranks
            Ranking.Insert(NewRank, Ranking[CurrentRank]);
            Ranking.erase(Ranking.begin() + CurrentRank + 1);
            for (auto i = NewRank + 1; i < std::min(Ranking.size(), CurrentRank + 1); i++)
            {
                SetNewRank(Ranking[i], i + 1, type);
            }
        }
        info->Rank[type] = NewRank + 1;

        return true;
    }

    void Envir::SetNewRank(RankCharacterInfo *Rank, int Index, unsigned char type)
    {
        CharacterInfo *Player = dynamic_cast<CharacterInfo*>(Rank->info);
        if (!(Player != nullptr))
        {
            return;
        }
        Player->Rank[type] = Index;
    }

    void Envir::RemoveRank(CharacterInfo *info)
    {
        std::vector<RankCharacterInfo*> Ranking;
        auto Rankindex = -1;
        //first check overall top           
        if (info->Level >= RankBottomLevel[0])
        {
            Ranking = RankTop;
            Rankindex = FindRank(Ranking, info, 0);
            if (Rankindex >= 0)
            {
                Ranking.erase(Ranking.begin() + Rankindex);
                for (auto i = Rankindex; i < Ranking.size()(); i++)
                {
                    SetNewRank(Ranking[i], i, 0);
                }
            }
        }
        //next class based top
        if (info->Level < RankBottomLevel[static_cast<unsigned char>(info->Class) + 1])
        {
            return;
        }
        {
            Ranking = RankTop;
            Rankindex = FindRank(Ranking, info, 1);
            if (Rankindex >= 0)
            {
                Ranking.erase(Ranking.begin() + Rankindex);
                for (auto i = Rankindex; i < Ranking.size()(); i++)
                {
                    SetNewRank(Ranking[i], i, 1);
                }
            }
        }
    }

    void Envir::CheckRankUpdate(CharacterInfo *info)
    {
        std::vector<RankCharacterInfo*> Ranking;
        RankCharacterInfo *NewRank;

        //first check overall top           
        if (info->Level >= RankBottomLevel[0])
        {
            Ranking = RankTop;
            if (!UpdateRank(Ranking, info,0))
            {
                if (TryAddRank(Ranking, info, 0))
                {
                    if (Ranking.size() > RankCount)
                    {
                        SetNewRank(Ranking[RankCount], 0, 0);
                        Ranking.erase(Ranking.begin() + RankCount);

                    }
                }
            }
            if (Ranking.size() >= RankCount)
            {
                NewRank = Ranking[Ranking.size() - 1];
                if (NewRank != nullptr)
                {
                    RankBottomLevel[0] = NewRank->level;
                }
            }
        }
        //now check class top
        if (info->Level >= RankBottomLevel[static_cast<unsigned char>(info->Class) + 1])
        {
            Ranking = RankClass[static_cast<unsigned char>(info->Class)];
            if (!UpdateRank(Ranking, info,1))
            {
                if (TryAddRank(Ranking, info, 1))
                {
                    if (Ranking.size() > RankCount)
                    {
                        SetNewRank(Ranking[RankCount], 0, 1);
                        Ranking.erase(Ranking.begin() + RankCount);
                    }
                }
            }

            if (Ranking.size() < RankCount)
            {
                return;
            }
            NewRank = Ranking[Ranking.size() - 1];
            if (NewRank != nullptr)
            {
                RankBottomLevel[static_cast<unsigned char>(info->Class) + 1] = NewRank->level;
            }
        }
    }

    void Envir::ReloadNPCs()
    {
        SaveGoods(true);

        auto keys = Scripts.Keys;

        for (auto key : *keys)
        {
            Scripts[key]->Load();
        }

        getMessageQueue()->Enqueue("NPC Scripts reloaded...");
    }

    void Envir::ReloadDrops()
    {
        for (auto item : MonsterInfoList)
        {
            item->LoadDrops();
        }
        getMessageQueue()->Enqueue("Drops reloaded...");
    }
}
